TextFormatterTests.cs 194 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157
  1. using System.Text;
  2. using Microsoft.VisualStudio.TestPlatform.Utilities;
  3. using Xunit.Abstractions;
  4. using static Terminal.Gui.SpinnerStyle;
  5. // Alias Console to MockConsole so we don't accidentally use Console
  6. namespace Terminal.Gui.TextTests;
  7. public class TextFormatterTests
  8. {
  9. private readonly ITestOutputHelper _output;
  10. public TextFormatterTests (ITestOutputHelper output) { _output = output; }
  11. public static IEnumerable<object []> CMGlyphs =>
  12. new List<object []> { new object [] { $"{CM.Glyphs.LeftBracket} Say Hello 你 {CM.Glyphs.RightBracket}", 16, 15 } };
  13. public static IEnumerable<object []> FormatEnvironmentNewLine =>
  14. new List<object []>
  15. {
  16. new object []
  17. {
  18. $"Line1{Environment.NewLine}Line2{Environment.NewLine}Line3{Environment.NewLine}",
  19. 60,
  20. new [] { "Line1", "Line2", "Line3" }
  21. }
  22. };
  23. public static IEnumerable<object []> SplitEnvironmentNewLine =>
  24. new List<object []>
  25. {
  26. new object []
  27. {
  28. $"First Line 界{Environment.NewLine}Second Line 界{Environment.NewLine}Third Line 界",
  29. new [] { "First Line 界", "Second Line 界", "Third Line 界" }
  30. },
  31. new object []
  32. {
  33. $"First Line 界{Environment.NewLine}Second Line 界{Environment.NewLine}Third Line 界{Environment.NewLine}",
  34. new [] { "First Line 界", "Second Line 界", "Third Line 界", "" }
  35. }
  36. };
  37. [Fact]
  38. public void Basic_Usage_With_AutoSize_True ()
  39. {
  40. var testText = "test";
  41. var testBounds = new Rectangle (0, 0, 100, 1);
  42. var tf = new TextFormatter ();
  43. // Manually set AutoSize to true
  44. tf.AutoSize = true;
  45. tf.Text = testText;
  46. Size expectedSize = new (testText.Length, 1);
  47. Assert.Equal (testText, tf.Text);
  48. Assert.Equal (Alignment.Start, tf.Alignment);
  49. Assert.Equal (expectedSize, tf.Size);
  50. tf.Draw (testBounds, new Attribute (), new Attribute ());
  51. Assert.Equal (expectedSize, tf.Size);
  52. Assert.NotEmpty (tf.GetLines ());
  53. tf.Alignment = Alignment.End;
  54. expectedSize = new (testText.Length, 1);
  55. Assert.Equal (testText, tf.Text);
  56. Assert.Equal (Alignment.End, tf.Alignment);
  57. Assert.Equal (expectedSize, tf.Size);
  58. tf.Draw (testBounds, new Attribute (), new Attribute ());
  59. Assert.Equal (expectedSize, tf.Size);
  60. Assert.NotEmpty (tf.GetLines ());
  61. tf.Alignment = Alignment.End;
  62. expectedSize = new (testText.Length, 1);
  63. tf.Size = expectedSize;
  64. Assert.Equal (testText, tf.Text);
  65. Assert.Equal (Alignment.End, tf.Alignment);
  66. Assert.Equal (expectedSize, tf.Size);
  67. tf.Draw (testBounds, new Attribute (), new Attribute ());
  68. Assert.Equal (expectedSize, tf.Size);
  69. Assert.NotEmpty (tf.GetLines ());
  70. tf.Alignment = Alignment.Center;
  71. expectedSize = new (testText.Length, 1);
  72. tf.Size = expectedSize;
  73. Assert.Equal (testText, tf.Text);
  74. Assert.Equal (Alignment.Center, tf.Alignment);
  75. Assert.Equal (expectedSize, tf.Size);
  76. tf.Draw (testBounds, new Attribute (), new Attribute ());
  77. Assert.Equal (expectedSize, tf.Size);
  78. Assert.NotEmpty (tf.GetLines ());
  79. }
  80. [Theory]
  81. [InlineData (null)]
  82. [InlineData ("")]
  83. public void CalcRect_Invalid_Returns_Empty (string text)
  84. {
  85. Assert.Equal (Rectangle.Empty, TextFormatter.CalcRect (0, 0, text));
  86. Assert.Equal (new (new (1, 2), Size.Empty), TextFormatter.CalcRect (1, 2, text));
  87. Assert.Equal (new (new (-1, -2), Size.Empty), TextFormatter.CalcRect (-1, -2, text));
  88. }
  89. [Theory]
  90. [InlineData ("line1\nline2", 5, 2)]
  91. [InlineData ("\nline2", 5, 2)]
  92. [InlineData ("\n\n", 0, 3)]
  93. [InlineData ("\n\n\n", 0, 4)]
  94. [InlineData ("line1\nline2\nline3long!", 10, 3)]
  95. [InlineData ("line1\nline2\n\n", 5, 4)]
  96. [InlineData ("line1\r\nline2", 5, 2)]
  97. [InlineData (" ~  s  gui.cs   master ↑10\n", 31, 2)]
  98. [InlineData ("\n ~  s  gui.cs   master ↑10", 31, 2)]
  99. [InlineData (" ~  s  gui.cs   master\n↑10", 27, 2)]
  100. public void CalcRect_MultiLine_Returns_nHigh (string text, int expectedWidth, int expectedLines)
  101. {
  102. Assert.Equal (new (0, 0, expectedWidth, expectedLines), TextFormatter.CalcRect (0, 0, text));
  103. string [] lines = text.Split (text.Contains (Environment.NewLine) ? Environment.NewLine : "\n");
  104. int maxWidth = lines.Max (s => s.GetColumns ());
  105. var lineWider = 0;
  106. for (var i = 0; i < lines.Length; i++)
  107. {
  108. int w = lines [i].GetColumns ();
  109. if (w == maxWidth)
  110. {
  111. lineWider = i;
  112. }
  113. }
  114. Assert.Equal (new (0, 0, maxWidth, expectedLines), TextFormatter.CalcRect (0, 0, text));
  115. Assert.Equal (
  116. new (
  117. 0,
  118. 0,
  119. lines [lineWider].ToRuneList ().Sum (r => Math.Max (r.GetColumns (), 0)),
  120. expectedLines
  121. ),
  122. TextFormatter.CalcRect (0, 0, text)
  123. );
  124. }
  125. [Theory]
  126. [InlineData ("test")]
  127. [InlineData (" ~  s  gui.cs   master ↑10")]
  128. public void CalcRect_SingleLine_Returns_1High (string text)
  129. {
  130. Assert.Equal (new (0, 0, text.GetRuneCount (), 1), TextFormatter.CalcRect (0, 0, text));
  131. Assert.Equal (new (0, 0, text.GetColumns (), 1), TextFormatter.CalcRect (0, 0, text));
  132. }
  133. [Theory]
  134. [InlineData (14, 1, TextDirection.LeftRight_TopBottom)]
  135. [InlineData (1, 14, TextDirection.TopBottom_LeftRight)]
  136. public void CalcRect_With_Combining_Runes (int width, int height, TextDirection textDirection)
  137. {
  138. var text = "Les Mise\u0328\u0301rables";
  139. Assert.Equal (new (0, 0, width, height), TextFormatter.CalcRect (0, 0, text, textDirection));
  140. }
  141. [Theory]
  142. [InlineData ("test", TextDirection.LeftRight_TopBottom)]
  143. [InlineData (" ~  s  gui.cs   master ↑10", TextDirection.LeftRight_TopBottom)]
  144. [InlineData ("Say Hello view4 你", TextDirection.LeftRight_TopBottom)]
  145. [InlineData ("Say Hello view4 你", TextDirection.RightLeft_TopBottom)]
  146. [InlineData ("Say Hello view4 你", TextDirection.LeftRight_BottomTop)]
  147. [InlineData ("Say Hello view4 你", TextDirection.RightLeft_BottomTop)]
  148. public void CalcRect_Horizontal_Width_Correct (string text, TextDirection textDirection)
  149. {
  150. // The width is the number of columns in the text
  151. Assert.Equal (new Size (text.GetColumns (), 1), TextFormatter.CalcRect (0, 0, text, textDirection).Size);
  152. }
  153. [Theory]
  154. [InlineData ("test", TextDirection.TopBottom_LeftRight)]
  155. [InlineData (" ~  s  gui.cs   master ↑10", TextDirection.TopBottom_LeftRight)]
  156. [InlineData ("Say Hello view4 你", TextDirection.TopBottom_LeftRight)]
  157. [InlineData ("Say Hello view4 你", TextDirection.TopBottom_RightLeft)]
  158. [InlineData ("Say Hello view4 你", TextDirection.BottomTop_LeftRight)]
  159. [InlineData ("Say Hello view4 你", TextDirection.BottomTop_RightLeft)]
  160. public void CalcRect_Vertical_Height_Correct (string text, TextDirection textDirection)
  161. {
  162. // The height is based both the number of lines and the number of wide chars
  163. Assert.Equal (new Size (1 + text.GetColumns () - text.Length, text.Length), TextFormatter.CalcRect (0, 0, text, textDirection).Size);
  164. }
  165. [Theory]
  166. [InlineData ("")]
  167. [InlineData (null)]
  168. [InlineData ("test")]
  169. public void ClipAndJustify_Invalid_Returns_Original (string text)
  170. {
  171. string expected = string.IsNullOrEmpty (text) ? text : "";
  172. Assert.Equal (expected, TextFormatter.ClipAndJustify (text, 0, Alignment.Start));
  173. Assert.Equal (expected, TextFormatter.ClipAndJustify (text, 0, Alignment.Start));
  174. Assert.Throws<ArgumentOutOfRangeException> (
  175. () =>
  176. TextFormatter.ClipAndJustify (text, -1, Alignment.Start)
  177. );
  178. }
  179. [Theory]
  180. [InlineData ("test", "", 0)]
  181. [InlineData ("test", "te", 2)]
  182. [InlineData ("test", "test", int.MaxValue)]
  183. [InlineData ("A sentence has words.", "A sentence has words.", 22)] // should fit
  184. [InlineData ("A sentence has words.", "A sentence has words.", 21)] // should fit
  185. [InlineData ("A sentence has words.", "A sentence has words.", int.MaxValue)] // should fit
  186. [InlineData ("A sentence has words.", "A sentence has words", 20)] // Should not fit
  187. [InlineData ("A sentence has words.", "A sentence", 10)] // Should not fit
  188. [InlineData ("A\tsentence\thas\twords.", "A sentence has words.", int.MaxValue)]
  189. [InlineData ("A\tsentence\thas\twords.", "A sentence", 10)]
  190. [InlineData ("line1\nline2\nline3long!", "line1\nline2\nline3long!", int.MaxValue)]
  191. [InlineData ("line1\nline2\nline3long!", "line1\nline", 10)]
  192. [InlineData (" ~  s  gui.cs   master ↑10", " ~  s  ", 10)] // Unicode
  193. [InlineData ("Ð ÑÐ", "Ð ÑÐ", 5)] // should fit
  194. [InlineData ("Ð ÑÐ", "Ð ÑÐ", 4)] // should fit
  195. [InlineData ("Ð ÑÐ", "Ð Ñ", 3)] // Should not fit
  196. public void ClipAndJustify_Valid_Centered (string text, string justifiedText, int maxWidth)
  197. {
  198. var alignment = Alignment.Center;
  199. var textDirection = TextDirection.LeftRight_TopBottom;
  200. var tabWidth = 1;
  201. Assert.Equal (
  202. justifiedText,
  203. TextFormatter.ClipAndJustify (text, maxWidth, alignment, textDirection, tabWidth)
  204. );
  205. int expectedClippedWidth = Math.Min (justifiedText.GetRuneCount (), maxWidth);
  206. Assert.Equal (
  207. justifiedText,
  208. TextFormatter.ClipAndJustify (text, maxWidth, alignment, textDirection, tabWidth)
  209. );
  210. Assert.True (justifiedText.GetRuneCount () <= maxWidth);
  211. Assert.True (justifiedText.GetColumns () <= maxWidth);
  212. Assert.Equal (expectedClippedWidth, justifiedText.GetRuneCount ());
  213. Assert.Equal (
  214. expectedClippedWidth,
  215. justifiedText.ToRuneList ().Sum (r => Math.Max (r.GetColumns (), 1))
  216. );
  217. Assert.True (expectedClippedWidth <= maxWidth);
  218. Assert.Equal (
  219. StringExtensions.ToString (justifiedText.ToRunes () [..expectedClippedWidth]),
  220. justifiedText
  221. );
  222. }
  223. [Theory]
  224. [InlineData ("test", "", 0)]
  225. [InlineData ("test", "te", 2)]
  226. [InlineData ("test", "test", int.MaxValue)] // This doesn't throw because it only create a word with length 1
  227. [InlineData ("A sentence has words.", "A sentence has words.", 22)] // should fit
  228. [InlineData ("A sentence has words.", "A sentence has words.", 21)] // should fit
  229. [InlineData (
  230. "A sentence has words.",
  231. "A sentence has words.",
  232. 500
  233. )] // should fit
  234. [InlineData ("A sentence has words.", "A sentence has words", 20)] // Should not fit
  235. [InlineData ("A sentence has words.", "A sentence", 10)] // Should not fit
  236. // Now throw System.OutOfMemoryException. See https://stackoverflow.com/questions/20672920/maxcapacity-of-stringbuilder
  237. //[InlineData ("A\tsentence\thas\twords.", "A sentence has words.", int.MaxValue)]
  238. [InlineData ("A\tsentence\thas\twords.", "A sentence", 10)]
  239. [InlineData (
  240. "line1\nline2\nline3long!",
  241. "line1\nline2\nline3long!",
  242. int.MaxValue
  243. )] // This doesn't throw because it only create a line with length 1
  244. [InlineData ("line1\nline2\nline3long!", "line1\nline", 10)]
  245. [InlineData (" ~  s  gui.cs   master ↑10", " ~  s  ", 10)] // Unicode
  246. [InlineData ("Ð ÑÐ", "Ð ÑÐ", 5)] // should fit
  247. [InlineData ("Ð ÑÐ", "Ð ÑÐ", 4)] // should fit
  248. [InlineData ("Ð ÑÐ", "Ð Ñ", 3)] // Should not fit
  249. public void ClipAndJustify_Valid_Justified (string text, string justifiedText, int maxWidth)
  250. {
  251. var alignment = Alignment.Fill;
  252. var textDirection = TextDirection.LeftRight_TopBottom;
  253. var tabWidth = 1;
  254. Assert.Equal (
  255. justifiedText,
  256. TextFormatter.ClipAndJustify (text, maxWidth, alignment, textDirection, tabWidth)
  257. );
  258. int expectedClippedWidth = Math.Min (justifiedText.GetRuneCount (), maxWidth);
  259. Assert.Equal (
  260. justifiedText,
  261. TextFormatter.ClipAndJustify (text, maxWidth, alignment, textDirection, tabWidth)
  262. );
  263. Assert.True (justifiedText.GetRuneCount () <= maxWidth);
  264. Assert.True (justifiedText.GetColumns () <= maxWidth);
  265. Assert.Equal (expectedClippedWidth, justifiedText.GetRuneCount ());
  266. Assert.Equal (
  267. expectedClippedWidth,
  268. justifiedText.ToRuneList ().Sum (r => Math.Max (r.GetColumns (), 1))
  269. );
  270. Assert.True (expectedClippedWidth <= maxWidth);
  271. Assert.Equal (
  272. StringExtensions.ToString (justifiedText.ToRunes () [..expectedClippedWidth]),
  273. justifiedText
  274. );
  275. // see Justify_ tests below
  276. }
  277. [Theory]
  278. [InlineData ("test", "", 0)]
  279. [InlineData ("test", "te", 2)]
  280. [InlineData ("test", "test", int.MaxValue)]
  281. [InlineData ("A sentence has words.", "A sentence has words.", 22)] // should fit
  282. [InlineData ("A sentence has words.", "A sentence has words.", 21)] // should fit
  283. [InlineData ("A sentence has words.", "A sentence has words.", int.MaxValue)] // should fit
  284. [InlineData ("A sentence has words.", "A sentence has words", 20)] // Should not fit
  285. [InlineData ("A sentence has words.", "A sentence", 10)] // Should not fit
  286. [InlineData ("A\tsentence\thas\twords.", "A sentence has words.", int.MaxValue)]
  287. [InlineData ("A\tsentence\thas\twords.", "A sentence", 10)]
  288. [InlineData ("line1\nline2\nline3long!", "line1\nline2\nline3long!", int.MaxValue)]
  289. [InlineData ("line1\nline2\nline3long!", "line1\nline", 10)]
  290. [InlineData (" ~  s  gui.cs   master ↑10", " ~  s  ", 10)] // Unicode
  291. [InlineData ("Ð ÑÐ", "Ð ÑÐ", 5)] // should fit
  292. [InlineData ("Ð ÑÐ", "Ð ÑÐ", 4)] // should fit
  293. [InlineData ("Ð ÑÐ", "Ð Ñ", 3)] // Should not fit
  294. public void ClipAndJustify_Valid_Left (string text, string justifiedText, int maxWidth)
  295. {
  296. var alignment = Alignment.Start;
  297. var textDirection = TextDirection.LeftRight_BottomTop;
  298. var tabWidth = 1;
  299. Assert.Equal (
  300. justifiedText,
  301. TextFormatter.ClipAndJustify (text, maxWidth, alignment, textDirection, tabWidth)
  302. );
  303. int expectedClippedWidth = Math.Min (justifiedText.GetRuneCount (), maxWidth);
  304. Assert.Equal (
  305. justifiedText,
  306. TextFormatter.ClipAndJustify (text, maxWidth, alignment, textDirection, tabWidth)
  307. );
  308. Assert.True (justifiedText.GetRuneCount () <= maxWidth);
  309. Assert.True (justifiedText.GetColumns () <= maxWidth);
  310. Assert.Equal (expectedClippedWidth, justifiedText.GetRuneCount ());
  311. Assert.Equal (
  312. expectedClippedWidth,
  313. justifiedText.ToRuneList ().Sum (r => Math.Max (r.GetColumns (), 1))
  314. );
  315. Assert.True (expectedClippedWidth <= maxWidth);
  316. Assert.Equal (
  317. StringExtensions.ToString (justifiedText.ToRunes () [..expectedClippedWidth]),
  318. justifiedText
  319. );
  320. }
  321. [Theory]
  322. [InlineData ("test", "", 0)]
  323. [InlineData ("test", "te", 2)]
  324. [InlineData ("test", "test", int.MaxValue)]
  325. [InlineData ("A sentence has words.", "A sentence has words.", 22)] // should fit
  326. [InlineData ("A sentence has words.", "A sentence has words.", 21)] // should fit
  327. [InlineData ("A sentence has words.", "A sentence has words.", int.MaxValue)] // should fit
  328. [InlineData ("A sentence has words.", "A sentence has words", 20)] // Should not fit
  329. [InlineData ("A sentence has words.", "A sentence", 10)] // Should not fit
  330. [InlineData ("A\tsentence\thas\twords.", "A sentence has words.", int.MaxValue)]
  331. [InlineData ("A\tsentence\thas\twords.", "A sentence", 10)]
  332. [InlineData ("line1\nline2\nline3long!", "line1\nline2\nline3long!", int.MaxValue)]
  333. [InlineData ("line1\nline2\nline3long!", "line1\nline", 10)]
  334. [InlineData (" ~  s  gui.cs   master ↑10", " ~  s  ", 10)] // Unicode
  335. [InlineData ("Ð ÑÐ", "Ð ÑÐ", 5)] // should fit
  336. [InlineData ("Ð ÑÐ", "Ð ÑÐ", 4)] // should fit
  337. [InlineData ("Ð ÑÐ", "Ð Ñ", 3)] // Should not fit
  338. public void ClipAndJustify_Valid_Right (string text, string justifiedText, int maxWidth)
  339. {
  340. var alignment = Alignment.End;
  341. var textDirection = TextDirection.LeftRight_BottomTop;
  342. var tabWidth = 1;
  343. Assert.Equal (
  344. justifiedText,
  345. TextFormatter.ClipAndJustify (text, maxWidth, alignment, textDirection, tabWidth)
  346. );
  347. int expectedClippedWidth = Math.Min (justifiedText.GetRuneCount (), maxWidth);
  348. Assert.Equal (
  349. justifiedText,
  350. TextFormatter.ClipAndJustify (text, maxWidth, alignment, textDirection, tabWidth)
  351. );
  352. Assert.True (justifiedText.GetRuneCount () <= maxWidth);
  353. Assert.True (justifiedText.GetColumns () <= maxWidth);
  354. Assert.Equal (expectedClippedWidth, justifiedText.GetRuneCount ());
  355. Assert.Equal (
  356. expectedClippedWidth,
  357. justifiedText.ToRuneList ().Sum (r => Math.Max (r.GetColumns (), 1))
  358. );
  359. Assert.True (expectedClippedWidth <= maxWidth);
  360. Assert.Equal (
  361. StringExtensions.ToString (justifiedText.ToRunes () [..expectedClippedWidth]),
  362. justifiedText
  363. );
  364. }
  365. [Theory]
  366. [InlineData (14, 1, TextDirection.LeftRight_TopBottom, "Les Misęrables")]
  367. [InlineData (1, 14, TextDirection.TopBottom_LeftRight, "L\ne\ns\n \nM\ni\ns\nę\nr\na\nb\nl\ne\ns")]
  368. [InlineData (
  369. 4,
  370. 4,
  371. TextDirection.TopBottom_LeftRight,
  372. @"
  373. LMre
  374. eias
  375. ssb
  376. ęl "
  377. )]
  378. public void Draw_With_Combining_Runes (int width, int height, TextDirection textDirection, string expected)
  379. {
  380. var driver = new FakeDriver ();
  381. driver.Init ();
  382. var text = "Les Mise\u0328\u0301rables";
  383. var tf = new TextFormatter ();
  384. tf.Direction = textDirection;
  385. tf.Text = text;
  386. Assert.True (tf.WordWrap);
  387. tf.Size = new (width, height);
  388. tf.Draw (
  389. new (0, 0, width, height),
  390. new Attribute (ColorName.White, ColorName.Black),
  391. new Attribute (ColorName.Blue, ColorName.Black),
  392. default (Rectangle),
  393. driver
  394. );
  395. TestHelpers.AssertDriverContentsWithFrameAre (expected, _output, driver);
  396. driver.End ();
  397. }
  398. [Fact]
  399. [SetupFakeDriver]
  400. public void FillRemaining_True_False ()
  401. {
  402. ((FakeDriver)Application.Driver).SetBufferSize (22, 5);
  403. Attribute [] attrs =
  404. {
  405. Attribute.Default, new Attribute (ColorName.Green, ColorName.BrightMagenta),
  406. new Attribute (ColorName.Blue, ColorName.Cyan)
  407. };
  408. var tf = new TextFormatter { Size = new (14, 3), Text = "Test\nTest long\nTest long long\n", MultiLine = true };
  409. tf.Draw (
  410. new (1, 1, 19, 3),
  411. attrs [1],
  412. attrs [2]);
  413. Assert.False (tf.FillRemaining);
  414. TestHelpers.AssertDriverContentsWithFrameAre (
  415. @"
  416. Test
  417. Test long
  418. Test long long",
  419. _output);
  420. TestHelpers.AssertDriverAttributesAre (
  421. @"
  422. 000000000000000000000
  423. 011110000000000000000
  424. 011111111100000000000
  425. 011111111111111000000
  426. 000000000000000000000",
  427. null,
  428. attrs);
  429. tf.FillRemaining = true;
  430. tf.Draw (
  431. new (1, 1, 19, 3),
  432. attrs [1],
  433. attrs [2]);
  434. TestHelpers.AssertDriverAttributesAre (
  435. @"
  436. 000000000000000000000
  437. 011111111111111111110
  438. 011111111111111111110
  439. 011111111111111111110
  440. 000000000000000000000",
  441. null,
  442. attrs);
  443. }
  444. [Theory]
  445. [InlineData ("_k Before", true, 0, (KeyCode)'K')] // lower case should return uppercase Hotkey
  446. [InlineData ("a_k Second", true, 1, (KeyCode)'K')]
  447. [InlineData ("Last _k", true, 5, (KeyCode)'K')]
  448. [InlineData ("After k_", false, -1, KeyCode.Null)]
  449. [InlineData ("Multiple _k and _R", true, 9, (KeyCode)'K')]
  450. [InlineData ("Non-english: _кдать", true, 13, (KeyCode)'к')] // Lower case Cryllic K (к)
  451. [InlineData ("_k Before", true, 0, (KeyCode)'K', true)] // Turn on FirstUpperCase and verify same results
  452. [InlineData ("a_k Second", true, 1, (KeyCode)'K', true)]
  453. [InlineData ("Last _k", true, 5, (KeyCode)'K', true)]
  454. [InlineData ("After k_", false, -1, KeyCode.Null, true)]
  455. [InlineData ("Multiple _k and _r", true, 9, (KeyCode)'K', true)]
  456. [InlineData ("Non-english: _кдать", true, 13, (KeyCode)'к', true)] // Cryllic K (К)
  457. public void FindHotKey_AlphaLowerCase_Succeeds (
  458. string text,
  459. bool expectedResult,
  460. int expectedHotPos,
  461. KeyCode expectedKey,
  462. bool supportFirstUpperCase = false
  463. )
  464. {
  465. var hotKeySpecifier = (Rune)'_';
  466. bool result = TextFormatter.FindHotKey (
  467. text,
  468. hotKeySpecifier,
  469. out int hotPos,
  470. out Key hotKey,
  471. supportFirstUpperCase
  472. );
  473. if (expectedResult)
  474. {
  475. Assert.True (result);
  476. }
  477. else
  478. {
  479. Assert.False (result);
  480. }
  481. Assert.Equal (expectedResult, result);
  482. Assert.Equal (expectedHotPos, hotPos);
  483. Assert.Equal (expectedKey, hotKey);
  484. }
  485. [Theory]
  486. [InlineData ("_K Before", true, 0, (KeyCode)'K')]
  487. [InlineData ("a_K Second", true, 1, (KeyCode)'K')]
  488. [InlineData ("Last _K", true, 5, (KeyCode)'K')]
  489. [InlineData ("After K_", false, -1, KeyCode.Null)]
  490. [InlineData ("Multiple _K and _R", true, 9, (KeyCode)'K')]
  491. [InlineData ("Non-english: _Кдать", true, 13, (KeyCode)'К')] // Cryllic K (К)
  492. [InlineData ("_K Before", true, 0, (KeyCode)'K', true)] // Turn on FirstUpperCase and verify same results
  493. [InlineData ("a_K Second", true, 1, (KeyCode)'K', true)]
  494. [InlineData ("Last _K", true, 5, (KeyCode)'K', true)]
  495. [InlineData ("After K_", false, -1, KeyCode.Null, true)]
  496. [InlineData ("Multiple _K and _R", true, 9, (KeyCode)'K', true)]
  497. [InlineData ("Non-english: _Кдать", true, 13, (KeyCode)'К', true)] // Cryllic K (К)
  498. public void FindHotKey_AlphaUpperCase_Succeeds (
  499. string text,
  500. bool expectedResult,
  501. int expectedHotPos,
  502. KeyCode expectedKey,
  503. bool supportFirstUpperCase = false
  504. )
  505. {
  506. var hotKeySpecifier = (Rune)'_';
  507. bool result = TextFormatter.FindHotKey (
  508. text,
  509. hotKeySpecifier,
  510. out int hotPos,
  511. out Key hotKey,
  512. supportFirstUpperCase
  513. );
  514. if (expectedResult)
  515. {
  516. Assert.True (result);
  517. }
  518. else
  519. {
  520. Assert.False (result);
  521. }
  522. Assert.Equal (expectedResult, result);
  523. Assert.Equal (expectedHotPos, hotPos);
  524. Assert.Equal (expectedKey, hotKey);
  525. }
  526. [Theory]
  527. [InlineData (null)]
  528. [InlineData ("")]
  529. [InlineData ("no hotkey")]
  530. [InlineData ("No hotkey, Upper Case")]
  531. [InlineData ("Non-english: Сохранить")]
  532. public void FindHotKey_Invalid_ReturnsFalse (string text)
  533. {
  534. var hotKeySpecifier = (Rune)'_';
  535. var supportFirstUpperCase = false;
  536. var hotPos = 0;
  537. Key hotKey = KeyCode.Null;
  538. var result = false;
  539. result = TextFormatter.FindHotKey (
  540. text,
  541. hotKeySpecifier,
  542. out hotPos,
  543. out hotKey,
  544. supportFirstUpperCase
  545. );
  546. Assert.False (result);
  547. Assert.Equal (-1, hotPos);
  548. Assert.Equal (KeyCode.Null, hotKey);
  549. }
  550. [Theory]
  551. [InlineData ("\"k before")]
  552. [InlineData ("ak second")]
  553. [InlineData ("last k")]
  554. [InlineData ("multiple k and r")]
  555. [InlineData ("12345")]
  556. [InlineData ("`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?")] // punctuation
  557. [InlineData (" ~  s  gui.cs   master ↑10")] // ~IsLetterOrDigit + Unicode
  558. [InlineData ("non-english: кдать")] // Lower case Cryllic K (к)
  559. public void FindHotKey_Legacy_FirstUpperCase_NotFound_Returns_False (string text)
  560. {
  561. var supportFirstUpperCase = true;
  562. var hotKeySpecifier = (Rune)0;
  563. bool result = TextFormatter.FindHotKey (
  564. text,
  565. hotKeySpecifier,
  566. out int hotPos,
  567. out Key hotKey,
  568. supportFirstUpperCase
  569. );
  570. Assert.False (result);
  571. Assert.Equal (-1, hotPos);
  572. Assert.Equal (KeyCode.Null, hotKey);
  573. }
  574. [Theory]
  575. [InlineData ("K Before", true, 0, (KeyCode)'K')]
  576. [InlineData ("aK Second", true, 1, (KeyCode)'K')]
  577. [InlineData ("last K", true, 5, (KeyCode)'K')]
  578. [InlineData ("multiple K and R", true, 9, (KeyCode)'K')]
  579. [InlineData ("non-english: Кдать", true, 13, (KeyCode)'К')] // Cryllic K (К)
  580. public void FindHotKey_Legacy_FirstUpperCase_Succeeds (
  581. string text,
  582. bool expectedResult,
  583. int expectedHotPos,
  584. KeyCode expectedKey
  585. )
  586. {
  587. var supportFirstUpperCase = true;
  588. var hotKeySpecifier = (Rune)0;
  589. bool result = TextFormatter.FindHotKey (
  590. text,
  591. hotKeySpecifier,
  592. out int hotPos,
  593. out Key hotKey,
  594. supportFirstUpperCase
  595. );
  596. if (expectedResult)
  597. {
  598. Assert.True (result);
  599. }
  600. else
  601. {
  602. Assert.False (result);
  603. }
  604. Assert.Equal (expectedResult, result);
  605. Assert.Equal (expectedHotPos, hotPos);
  606. Assert.Equal (expectedKey, hotKey);
  607. }
  608. [Theory]
  609. [InlineData ("_1 Before", true, 0, (KeyCode)'1')] // Digits
  610. [InlineData ("a_1 Second", true, 1, (KeyCode)'1')]
  611. [InlineData ("Last _1", true, 5, (KeyCode)'1')]
  612. [InlineData ("After 1_", false, -1, KeyCode.Null)]
  613. [InlineData ("Multiple _1 and _2", true, 9, (KeyCode)'1')]
  614. [InlineData ("_1 Before", true, 0, (KeyCode)'1', true)] // Turn on FirstUpperCase and verify same results
  615. [InlineData ("a_1 Second", true, 1, (KeyCode)'1', true)]
  616. [InlineData ("Last _1", true, 5, (KeyCode)'1', true)]
  617. [InlineData ("After 1_", false, -1, KeyCode.Null, true)]
  618. [InlineData ("Multiple _1 and _2", true, 9, (KeyCode)'1', true)]
  619. public void FindHotKey_Numeric_Succeeds (
  620. string text,
  621. bool expectedResult,
  622. int expectedHotPos,
  623. KeyCode expectedKey,
  624. bool supportFirstUpperCase = false
  625. )
  626. {
  627. var hotKeySpecifier = (Rune)'_';
  628. bool result = TextFormatter.FindHotKey (
  629. text,
  630. hotKeySpecifier,
  631. out int hotPos,
  632. out Key hotKey,
  633. supportFirstUpperCase
  634. );
  635. if (expectedResult)
  636. {
  637. Assert.True (result);
  638. }
  639. else
  640. {
  641. Assert.False (result);
  642. }
  643. Assert.Equal (expectedResult, result);
  644. Assert.Equal (expectedHotPos, hotPos);
  645. Assert.Equal (expectedKey, hotKey);
  646. }
  647. [Theory]
  648. [InlineData ("_\"k before", true, (KeyCode)'"')] // BUGBUG: Not sure why this fails. " is a normal char
  649. [InlineData ("\"_k before", true, KeyCode.K)]
  650. [InlineData ("_`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?", true, (KeyCode)'`')]
  651. [InlineData ("`_~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?", true, (KeyCode)'~')]
  652. [InlineData (
  653. "`~!@#$%^&*()-__=+[{]}\\|;:'\",<.>/?",
  654. true,
  655. (KeyCode)'='
  656. )] // BUGBUG: Not sure why this fails. Ignore the first and consider the second
  657. [InlineData ("_ ~  s  gui.cs   master ↑10", true, (KeyCode)'')] // ~IsLetterOrDigit + Unicode
  658. [InlineData (" ~  s  gui.cs  _ master ↑10", true, (KeyCode)'')] // ~IsLetterOrDigit + Unicode
  659. [InlineData ("non-english: _кдать", true, (KeyCode)'к')] // Lower case Cryllic K (к)
  660. public void FindHotKey_Symbols_Returns_Symbol (string text, bool found, KeyCode expected)
  661. {
  662. var hotKeySpecifier = (Rune)'_';
  663. bool result = TextFormatter.FindHotKey (text, hotKeySpecifier, out int _, out Key hotKey);
  664. Assert.Equal (found, result);
  665. Assert.Equal (expected, hotKey);
  666. }
  667. [Fact]
  668. public void Format_Dont_Throw_ArgumentException_With_WordWrap_As_False_And_Keep_End_Spaces_As_True ()
  669. {
  670. Exception exception = Record.Exception (
  671. () =>
  672. TextFormatter.Format (
  673. "Some text",
  674. 4,
  675. Alignment.Start,
  676. false,
  677. true
  678. )
  679. );
  680. Assert.Null (exception);
  681. }
  682. [Theory]
  683. [InlineData (
  684. "Hello world, how are you today? Pretty neat!",
  685. 44,
  686. 80,
  687. "Hello world, how are you today? Pretty neat!"
  688. )]
  689. public void Format_Justified_Always_Returns_Text_Width_Equal_To_Passed_Width_Horizontal (
  690. string text,
  691. int runeCount,
  692. int maxWidth,
  693. string justifiedText
  694. )
  695. {
  696. Assert.Equal (runeCount, text.GetRuneCount ());
  697. var fmtText = string.Empty;
  698. for (int i = text.GetRuneCount (); i < maxWidth; i++)
  699. {
  700. fmtText = TextFormatter.Format (text, i, Alignment.Fill, false, true) [0];
  701. Assert.Equal (i, fmtText.GetRuneCount ());
  702. char c = fmtText [^1];
  703. Assert.True (text.EndsWith (c));
  704. }
  705. Assert.Equal (justifiedText, fmtText);
  706. }
  707. [Theory]
  708. [InlineData (
  709. "Hello world, how are you today? Pretty neat!",
  710. 44,
  711. 80,
  712. "Hello world, how are you today? Pretty neat!"
  713. )]
  714. public void Format_Justified_Always_Returns_Text_Width_Equal_To_Passed_Width_Vertical (
  715. string text,
  716. int runeCount,
  717. int maxWidth,
  718. string justifiedText
  719. )
  720. {
  721. Assert.Equal (runeCount, text.GetRuneCount ());
  722. var fmtText = string.Empty;
  723. for (int i = text.GetRuneCount (); i < maxWidth; i++)
  724. {
  725. fmtText = TextFormatter.Format (
  726. text,
  727. i,
  728. Alignment.Fill,
  729. false,
  730. true,
  731. 0,
  732. TextDirection.TopBottom_LeftRight
  733. ) [0];
  734. Assert.Equal (i, fmtText.GetRuneCount ());
  735. char c = fmtText [^1];
  736. Assert.True (text.EndsWith (c));
  737. }
  738. Assert.Equal (justifiedText, fmtText);
  739. }
  740. [Theory]
  741. [InlineData ("Truncate", 3, "Tru")]
  742. [InlineData ("デモエムポンズ", 3, "デ")]
  743. public void Format_Truncate_Simple_And_Wide_Runes (string text, int width, string expected)
  744. {
  745. List<string> list = TextFormatter.Format (text, width, false, false);
  746. Assert.Equal (expected, list [^1]);
  747. }
  748. [Theory]
  749. [MemberData (nameof (FormatEnvironmentNewLine))]
  750. public void Format_With_PreserveTrailingSpaces_And_Without_PreserveTrailingSpaces (
  751. string text,
  752. int width,
  753. IEnumerable<string> expected
  754. )
  755. {
  756. var preserveTrailingSpaces = false;
  757. List<string> formated = TextFormatter.Format (text, width, false, true, preserveTrailingSpaces);
  758. Assert.Equal (expected, formated);
  759. preserveTrailingSpaces = true;
  760. formated = TextFormatter.Format (text, width, false, true, preserveTrailingSpaces);
  761. Assert.Equal (expected, formated);
  762. }
  763. [Theory]
  764. [InlineData (
  765. " A sentence has words. \n This is the second Line - 2. ",
  766. 4,
  767. -50,
  768. Alignment.Start,
  769. true,
  770. false,
  771. new [] { " A", "sent", "ence", "has", "word", "s. ", " Thi", "s is", "the", "seco", "nd", "Line", "- 2." },
  772. " Asentencehaswords. This isthesecondLine- 2."
  773. )]
  774. [InlineData (
  775. " A sentence has words. \n This is the second Line - 2. ",
  776. 4,
  777. -50,
  778. Alignment.Start,
  779. true,
  780. true,
  781. new []
  782. {
  783. " A ",
  784. "sent",
  785. "ence",
  786. " ",
  787. "has ",
  788. "word",
  789. "s. ",
  790. " ",
  791. "This",
  792. " is ",
  793. "the ",
  794. "seco",
  795. "nd ",
  796. "Line",
  797. " - ",
  798. "2. "
  799. },
  800. " A sentence has words. This is the second Line - 2. "
  801. )]
  802. public void Format_WordWrap_PreserveTrailingSpaces (
  803. string text,
  804. int maxWidth,
  805. int widthOffset,
  806. Alignment alignment,
  807. bool wrap,
  808. bool preserveTrailingSpaces,
  809. IEnumerable<string> resultLines,
  810. string expectedWrappedText
  811. )
  812. {
  813. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  814. List<string> list = TextFormatter.Format (text, maxWidth, alignment, wrap, preserveTrailingSpaces);
  815. Assert.Equal (list.Count, resultLines.Count ());
  816. Assert.Equal (resultLines, list);
  817. var wrappedText = string.Empty;
  818. foreach (string txt in list)
  819. {
  820. wrappedText += txt;
  821. }
  822. Assert.Equal (expectedWrappedText, wrappedText);
  823. }
  824. [Theory]
  825. [InlineData ("Hello World", 11)]
  826. [InlineData ("こんにちは世界", 14)]
  827. public void GetColumns_Simple_And_Wide_Runes (string text, int width) { Assert.Equal (width, text.GetColumns ()); }
  828. [Theory]
  829. [InlineData ("Hello World", 6, 6)]
  830. [InlineData ("こんにちは 世界", 6, 3)]
  831. [MemberData (nameof (CMGlyphs))]
  832. public void GetLengthThatFits_List_Simple_And_Wide_Runes (string text, int columns, int expectedLength)
  833. {
  834. List<Rune> runes = text.ToRuneList ();
  835. Assert.Equal (expectedLength, TextFormatter.GetLengthThatFits (runes, columns));
  836. }
  837. [Theory]
  838. [InlineData ("test", 3, 3)]
  839. [InlineData ("test", 4, 4)]
  840. [InlineData ("test", 10, 4)]
  841. public void GetLengthThatFits_Runelist (string text, int columns, int expectedLength)
  842. {
  843. List<Rune> runes = text.ToRuneList ();
  844. Assert.Equal (expectedLength, TextFormatter.GetLengthThatFits (runes, columns));
  845. }
  846. [Theory]
  847. [InlineData ("Hello World", 6, 6)]
  848. [InlineData ("こんにちは 世界", 6, 3)]
  849. public void GetLengthThatFits_Simple_And_Wide_Runes (string text, int columns, int expectedLength)
  850. {
  851. Assert.Equal (expectedLength, TextFormatter.GetLengthThatFits (text, columns));
  852. }
  853. [Theory]
  854. [InlineData ("test", 3, 3)]
  855. [InlineData ("test", 4, 4)]
  856. [InlineData ("test", 10, 4)]
  857. [InlineData ("test", 1, 1)]
  858. [InlineData ("test", 0, 0)]
  859. [InlineData ("test", -1, 0)]
  860. [InlineData (null, -1, 0)]
  861. [InlineData ("", -1, 0)]
  862. public void GetLengthThatFits_String (string text, int columns, int expectedLength)
  863. {
  864. Assert.Equal (expectedLength, TextFormatter.GetLengthThatFits (text, columns));
  865. }
  866. [Fact]
  867. public void GetLengthThatFits_With_Combining_Runes ()
  868. {
  869. var text = "Les Mise\u0328\u0301rables";
  870. Assert.Equal (16, TextFormatter.GetLengthThatFits (text, 14));
  871. }
  872. [Fact]
  873. public void GetMaxColsForWidth_With_Combining_Runes ()
  874. {
  875. List<string> text = new () { "Les Mis", "e\u0328\u0301", "rables" };
  876. Assert.Equal (1, TextFormatter.GetMaxColsForWidth (text, 1));
  877. }
  878. [Theory]
  879. [InlineData (new [] { "0123456789" }, 1)]
  880. [InlineData (new [] { "Hello World" }, 1)]
  881. [InlineData (new [] { "Hello", "World" }, 2)]
  882. [InlineData (new [] { "こんにちは", "世界" }, 4)]
  883. public void GetColumnsRequiredForVerticalText_List_GetsWidth (IEnumerable<string> text, int expectedWidth)
  884. {
  885. Assert.Equal (expectedWidth, TextFormatter.GetColumnsRequiredForVerticalText (text.ToList ()));
  886. }
  887. [Theory]
  888. [InlineData (new [] { "Hello World" }, 1, 0, 1, 1)]
  889. [InlineData (new [] { "Hello", "World" }, 2, 1, 1, 1)]
  890. [InlineData (new [] { "こんにちは", "世界" }, 4, 1, 1, 2)]
  891. public void GetColumnsRequiredForVerticalText_List_Simple_And_Wide_Runes (
  892. IEnumerable<string> text,
  893. int expectedWidth,
  894. int index,
  895. int length,
  896. int expectedIndexWidth
  897. )
  898. {
  899. Assert.Equal (expectedWidth, TextFormatter.GetColumnsRequiredForVerticalText (text.ToList ()));
  900. Assert.Equal (expectedIndexWidth, TextFormatter.GetColumnsRequiredForVerticalText (text.ToList (), index, length));
  901. }
  902. [Fact]
  903. public void GetColumnsRequiredForVerticalText_List_With_Combining_Runes ()
  904. {
  905. List<string> text = new () { "Les Mis", "e\u0328\u0301", "rables" };
  906. Assert.Equal (1, TextFormatter.GetColumnsRequiredForVerticalText (text, 1, 1));
  907. }
  908. //[Fact]
  909. //public void GetWidestLineLength_With_Combining_Runes ()
  910. //{
  911. // var text = "Les Mise\u0328\u0301rables";
  912. // Assert.Equal (1, TextFormatter.GetWidestLineLength (text, 1, 1));
  913. //}
  914. [Fact]
  915. public void Internal_Tests ()
  916. {
  917. var tf = new TextFormatter ();
  918. Assert.Equal (KeyCode.Null, tf.HotKey);
  919. tf.HotKey = KeyCode.CtrlMask | KeyCode.Q;
  920. Assert.Equal (KeyCode.CtrlMask | KeyCode.Q, tf.HotKey);
  921. }
  922. [Theory]
  923. [InlineData ("")]
  924. [InlineData (null)]
  925. [InlineData ("test")]
  926. public void Justify_Invalid (string text)
  927. {
  928. Assert.Equal (text, TextFormatter.Justify (text, 0));
  929. Assert.Equal (text, TextFormatter.Justify (text, 0));
  930. Assert.Throws<ArgumentOutOfRangeException> (() => TextFormatter.Justify (text, -1));
  931. }
  932. [Theory]
  933. // Even # of spaces
  934. // 0123456789
  935. [InlineData ("012 456 89", "012 456 89", 10, 0, "+", true)]
  936. [InlineData ("012 456 89", "012++456+89", 11, 1)]
  937. [InlineData ("012 456 89", "012 456 89", 12, 2, "++", true)]
  938. [InlineData ("012 456 89", "012+++456++89", 13, 3)]
  939. [InlineData ("012 456 89", "012 456 89", 14, 4, "+++", true)]
  940. [InlineData ("012 456 89", "012++++456+++89", 15, 5)]
  941. [InlineData ("012 456 89", "012 456 89", 16, 6, "++++", true)]
  942. [InlineData ("012 456 89", "012 456 89", 30, 20, "+++++++++++", true)]
  943. [InlineData ("012 456 89", "012+++++++++++++456++++++++++++89", 33, 23)]
  944. // Odd # of spaces
  945. // 01234567890123
  946. [InlineData ("012 456 89 end", "012 456 89 end", 14, 0, "+", true)]
  947. [InlineData ("012 456 89 end", "012++456+89+end", 15, 1)]
  948. [InlineData ("012 456 89 end", "012++456++89+end", 16, 2)]
  949. [InlineData ("012 456 89 end", "012 456 89 end", 17, 3, "++", true)]
  950. [InlineData ("012 456 89 end", "012+++456++89++end", 18, 4)]
  951. [InlineData ("012 456 89 end", "012+++456+++89++end", 19, 5)]
  952. [InlineData ("012 456 89 end", "012 456 89 end", 20, 6, "+++", true)]
  953. [InlineData ("012 456 89 end", "012++++++++456++++++++89+++++++end", 34, 20)]
  954. [InlineData ("012 456 89 end", "012+++++++++456+++++++++89++++++++end", 37, 23)]
  955. // Unicode
  956. // Even # of chars
  957. // 0123456789
  958. [InlineData ("пÑРвРÑ", "пÑРвРÑ", 10, 0, "+", true)]
  959. [InlineData ("пÑРвРÑ", "пÑÐ++вÐ+Ñ", 11, 1)]
  960. [InlineData ("пÑРвРÑ", "пÑРвРÑ", 12, 2, "++", true)]
  961. [InlineData ("пÑРвРÑ", "пÑÐ+++вÐ++Ñ", 13, 3)]
  962. [InlineData ("пÑРвРÑ", "пÑРвРÑ", 14, 4, "+++", true)]
  963. [InlineData ("пÑРвРÑ", "пÑÐ++++вÐ+++Ñ", 15, 5)]
  964. [InlineData ("пÑРвРÑ", "пÑРвРÑ", 16, 6, "++++", true)]
  965. [InlineData ("пÑРвРÑ", "пÑРвРÑ", 30, 20, "+++++++++++", true)]
  966. [InlineData ("пÑРвРÑ", "пÑÐ+++++++++++++вÐ++++++++++++Ñ", 33, 23)]
  967. // Unicode
  968. // Odd # of chars
  969. // 0123456789
  970. [InlineData ("Ð ÑРвРÑ", "Ð ÑРвРÑ", 10, 0, "+", true)]
  971. [InlineData ("Ð ÑРвРÑ", "Ð++ÑÐ+вÐ+Ñ", 11, 1)]
  972. [InlineData ("Ð ÑРвРÑ", "Ð++ÑÐ++вÐ+Ñ", 12, 2)]
  973. [InlineData ("Ð ÑРвРÑ", "Ð ÑРвРÑ", 13, 3, "++", true)]
  974. [InlineData ("Ð ÑРвРÑ", "Ð+++ÑÐ++вÐ++Ñ", 14, 4)]
  975. [InlineData ("Ð ÑРвРÑ", "Ð+++ÑÐ+++вÐ++Ñ", 15, 5)]
  976. [InlineData ("Ð ÑРвРÑ", "Ð ÑРвРÑ", 16, 6, "+++", true)]
  977. [InlineData ("Ð ÑРвРÑ", "Ð++++++++ÑÐ++++++++вÐ+++++++Ñ", 30, 20)]
  978. [InlineData ("Ð ÑРвРÑ", "Ð+++++++++ÑÐ+++++++++вÐ++++++++Ñ", 33, 23)]
  979. public void Justify_Sentence (
  980. string text,
  981. string justifiedText,
  982. int forceToWidth,
  983. int widthOffset,
  984. string replaceWith = null,
  985. bool replace = false
  986. )
  987. {
  988. var fillChar = '+';
  989. Assert.Equal (forceToWidth, text.GetRuneCount () + widthOffset);
  990. if (replace)
  991. {
  992. justifiedText = text.Replace (" ", replaceWith);
  993. }
  994. Assert.Equal (justifiedText, TextFormatter.Justify (text, forceToWidth, fillChar));
  995. Assert.True (Math.Abs (forceToWidth - justifiedText.GetRuneCount ()) < text.Count (s => s == ' '));
  996. Assert.True (Math.Abs (forceToWidth - justifiedText.GetColumns ()) < text.Count (s => s == ' '));
  997. }
  998. [Theory]
  999. [InlineData ("word")] // Even # of chars
  1000. [InlineData ("word.")] // Odd # of chars
  1001. [InlineData ("пÑивеÑ")] // Unicode (even #)
  1002. [InlineData ("пÑивеÑ.")] // Unicode (odd # of chars)
  1003. public void Justify_SingleWord (string text)
  1004. {
  1005. string justifiedText = text;
  1006. var fillChar = '+';
  1007. int width = text.GetRuneCount ();
  1008. Assert.Equal (justifiedText, TextFormatter.Justify (text, width, fillChar));
  1009. width = text.GetRuneCount () + 1;
  1010. Assert.Equal (justifiedText, TextFormatter.Justify (text, width, fillChar));
  1011. width = text.GetRuneCount () + 2;
  1012. Assert.Equal (justifiedText, TextFormatter.Justify (text, width, fillChar));
  1013. width = text.GetRuneCount () + 10;
  1014. Assert.Equal (justifiedText, TextFormatter.Justify (text, width, fillChar));
  1015. width = text.GetRuneCount () + 11;
  1016. Assert.Equal (justifiedText, TextFormatter.Justify (text, width, fillChar));
  1017. }
  1018. [Theory]
  1019. [InlineData ("Single Line 界", 14)]
  1020. [InlineData ("First Line 界\nSecond Line 界\nThird Line 界\n", 14)]
  1021. public void MaxWidthLine_With_And_Without_Newlines (string text, int expected) { Assert.Equal (expected, TextFormatter.GetWidestLineLength (text)); }
  1022. [Theory]
  1023. [InlineData (
  1024. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1025. 0,
  1026. 0,
  1027. false,
  1028. new [] { "" }
  1029. )]
  1030. [InlineData (
  1031. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1032. 0,
  1033. 1,
  1034. false,
  1035. new [] { "" }
  1036. )]
  1037. [InlineData (
  1038. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1039. 1,
  1040. 0,
  1041. false,
  1042. new [] { "" }
  1043. )]
  1044. [InlineData (
  1045. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1046. 0,
  1047. 0,
  1048. true,
  1049. new [] { "" }
  1050. )]
  1051. [InlineData (
  1052. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1053. 0,
  1054. 1,
  1055. true,
  1056. new [] { "" }
  1057. )]
  1058. [InlineData (
  1059. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1060. 1,
  1061. 0,
  1062. true,
  1063. new [] { "" }
  1064. )]
  1065. [InlineData (
  1066. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1067. 6,
  1068. 5,
  1069. false,
  1070. new [] { "First " }
  1071. )]
  1072. [InlineData ("1\n2\n3\n4\n5\n6", 6, 5, false, new [] { "1 2 3 " })]
  1073. [InlineData (
  1074. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1075. 6,
  1076. 5,
  1077. true,
  1078. new [] { "First ", "Second", "Third ", "Forty ", "Fiftee" }
  1079. )]
  1080. [InlineData ("第一行\n第二行\n第三行\n四十行\n第十五行\n七十行", 5, 5, false, new [] { "第一" })]
  1081. [InlineData ("第一行\n第二行\n第三行\n四十行\n第十五行\n七十行", 5, 5, true, new [] { "第一", "第二", "第三", "四十", "第十" })]
  1082. public void MultiLine_WordWrap_False_Horizontal_Direction (
  1083. string text,
  1084. int maxWidth,
  1085. int maxHeight,
  1086. bool multiLine,
  1087. IEnumerable<string> resultLines
  1088. )
  1089. {
  1090. var tf = new TextFormatter
  1091. {
  1092. Text = text, Size = new (maxWidth, maxHeight), WordWrap = false, MultiLine = multiLine
  1093. };
  1094. Assert.False (tf.AutoSize);
  1095. Assert.False (tf.WordWrap);
  1096. Assert.True (tf.MultiLine == multiLine);
  1097. Assert.Equal (TextDirection.LeftRight_TopBottom, tf.Direction);
  1098. List<string> splitLines = tf.GetLines ();
  1099. Assert.Equal (splitLines.Count, resultLines.Count ());
  1100. Assert.Equal (splitLines, resultLines);
  1101. }
  1102. [Theory]
  1103. [InlineData (
  1104. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1105. 0,
  1106. 0,
  1107. false,
  1108. new [] { "" }
  1109. )]
  1110. [InlineData (
  1111. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1112. 0,
  1113. 1,
  1114. false,
  1115. new [] { "" }
  1116. )]
  1117. [InlineData (
  1118. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1119. 1,
  1120. 0,
  1121. false,
  1122. new [] { "" }
  1123. )]
  1124. [InlineData (
  1125. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1126. 0,
  1127. 0,
  1128. true,
  1129. new [] { "" }
  1130. )]
  1131. [InlineData (
  1132. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1133. 0,
  1134. 1,
  1135. true,
  1136. new [] { "" }
  1137. )]
  1138. [InlineData (
  1139. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1140. 1,
  1141. 0,
  1142. true,
  1143. new [] { "" }
  1144. )]
  1145. [InlineData (
  1146. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1147. 6,
  1148. 5,
  1149. false,
  1150. new [] { "First" }
  1151. )]
  1152. [InlineData ("1\n2\n3\n4\n5\n6", 6, 5, false, new [] { "1 2 3" })]
  1153. [InlineData (
  1154. "First Line\nSecond Line\nThird Line\nForty Line\nFifteenth Line\nSeventy Line",
  1155. 6,
  1156. 5,
  1157. true,
  1158. new [] { "First", "Secon", "Third", "Forty", "Fifte", "Seven" }
  1159. )]
  1160. [InlineData ("第一行\n第二行\n第三行\n四十行\n第十五行\n七十行", 5, 5, false, new [] { "第一行 第" })]
  1161. [InlineData ("第一行\n第二行\n第三行\n四十行\n第十五行\n七十行", 5, 5, true, new [] { "第一行", "第二行" })]
  1162. public void MultiLine_WordWrap_False_Vertical_Direction (
  1163. string text,
  1164. int maxWidth,
  1165. int maxHeight,
  1166. bool multiLine,
  1167. IEnumerable<string> resultLines
  1168. )
  1169. {
  1170. var tf = new TextFormatter
  1171. {
  1172. Text = text,
  1173. Size = new (maxWidth, maxHeight),
  1174. WordWrap = false,
  1175. MultiLine = multiLine,
  1176. Direction = TextDirection.TopBottom_LeftRight
  1177. };
  1178. Assert.False (tf.AutoSize);
  1179. Assert.False (tf.WordWrap);
  1180. Assert.True (tf.MultiLine == multiLine);
  1181. Assert.Equal (TextDirection.TopBottom_LeftRight, tf.Direction);
  1182. List<string> splitLines = tf.GetLines ();
  1183. Assert.Equal (splitLines.Count, resultLines.Count ());
  1184. Assert.Equal (splitLines, resultLines);
  1185. }
  1186. [Fact]
  1187. public void NeedsFormat_Sets ()
  1188. {
  1189. var testText = "test";
  1190. var testBounds = new Rectangle (0, 0, 100, 1);
  1191. var tf = new TextFormatter ();
  1192. tf.Text = "test";
  1193. Assert.True (tf.NeedsFormat); // get_Lines causes a Format
  1194. Assert.NotEmpty (tf.GetLines ());
  1195. Assert.False (tf.NeedsFormat); // get_Lines causes a Format
  1196. Assert.Equal (testText, tf.Text);
  1197. tf.Draw (testBounds, new Attribute (), new Attribute ());
  1198. Assert.False (tf.NeedsFormat);
  1199. tf.Size = new (1, 1);
  1200. Assert.True (tf.NeedsFormat);
  1201. Assert.NotEmpty (tf.GetLines ());
  1202. Assert.False (tf.NeedsFormat); // get_Lines causes a Format
  1203. tf.Alignment = Alignment.Center;
  1204. Assert.True (tf.NeedsFormat);
  1205. Assert.NotEmpty (tf.GetLines ());
  1206. Assert.False (tf.NeedsFormat); // get_Lines causes a Format
  1207. }
  1208. [Theory]
  1209. [InlineData ("", -1, Alignment.Start, false, 0)]
  1210. [InlineData (null, 0, Alignment.Start, false, 1)]
  1211. [InlineData (null, 0, Alignment.Start, true, 1)]
  1212. [InlineData ("", 0, Alignment.Start, false, 1)]
  1213. [InlineData ("", 0, Alignment.Start, true, 1)]
  1214. public void Reformat_Invalid (string text, int maxWidth, Alignment alignment, bool wrap, int linesCount)
  1215. {
  1216. if (maxWidth < 0)
  1217. {
  1218. Assert.Throws<ArgumentOutOfRangeException> (
  1219. () =>
  1220. TextFormatter.Format (text, maxWidth, alignment, wrap)
  1221. );
  1222. }
  1223. else
  1224. {
  1225. List<string> list = TextFormatter.Format (text, maxWidth, alignment, wrap);
  1226. Assert.NotEmpty (list);
  1227. Assert.True (list.Count == linesCount);
  1228. Assert.Equal (string.Empty, list [0]);
  1229. }
  1230. }
  1231. [Theory]
  1232. [InlineData ("A sentence has words.\nLine 2.", 0, -29, Alignment.Start, false, 1, true)]
  1233. [InlineData ("A sentence has words.\nLine 2.", 1, -28, Alignment.Start, false, 1, false)]
  1234. [InlineData ("A sentence has words.\nLine 2.", 5, -24, Alignment.Start, false, 1, false)]
  1235. [InlineData ("A sentence has words.\nLine 2.", 28, -1, Alignment.Start, false, 1, false)]
  1236. // no clip
  1237. [InlineData ("A sentence has words.\nLine 2.", 29, 0, Alignment.Start, false, 1, false)]
  1238. [InlineData ("A sentence has words.\nLine 2.", 30, 1, Alignment.Start, false, 1, false)]
  1239. [InlineData ("A sentence has words.\r\nLine 2.", 0, -30, Alignment.Start, false, 1, true)]
  1240. [InlineData ("A sentence has words.\r\nLine 2.", 1, -29, Alignment.Start, false, 1, false)]
  1241. [InlineData ("A sentence has words.\r\nLine 2.", 5, -25, Alignment.Start, false, 1, false)]
  1242. [InlineData ("A sentence has words.\r\nLine 2.", 29, -1, Alignment.Start, false, 1, false, 1)]
  1243. [InlineData ("A sentence has words.\r\nLine 2.", 30, 0, Alignment.Start, false, 1, false)]
  1244. [InlineData ("A sentence has words.\r\nLine 2.", 31, 1, Alignment.Start, false, 1, false)]
  1245. public void Reformat_NoWordrap_NewLines_MultiLine_False (
  1246. string text,
  1247. int maxWidth,
  1248. int widthOffset,
  1249. Alignment alignment,
  1250. bool wrap,
  1251. int linesCount,
  1252. bool stringEmpty,
  1253. int clipWidthOffset = 0
  1254. )
  1255. {
  1256. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  1257. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth) + clipWidthOffset;
  1258. List<string> list = TextFormatter.Format (text, maxWidth, alignment, wrap);
  1259. Assert.NotEmpty (list);
  1260. Assert.True (list.Count == linesCount);
  1261. if (stringEmpty)
  1262. {
  1263. Assert.Equal (string.Empty, list [0]);
  1264. }
  1265. else
  1266. {
  1267. Assert.NotEqual (string.Empty, list [0]);
  1268. }
  1269. if (text.Contains ("\r\n") && maxWidth > 0)
  1270. {
  1271. Assert.Equal (
  1272. StringExtensions.ToString (text.ToRunes () [..expectedClippedWidth])
  1273. .Replace ("\r\n", " "),
  1274. list [0]
  1275. );
  1276. }
  1277. else if (text.Contains ('\n') && maxWidth > 0)
  1278. {
  1279. Assert.Equal (
  1280. StringExtensions.ToString (text.ToRunes () [..expectedClippedWidth])
  1281. .Replace ("\n", " "),
  1282. list [0]
  1283. );
  1284. }
  1285. else
  1286. {
  1287. Assert.Equal (StringExtensions.ToString (text.ToRunes () [..expectedClippedWidth]), list [0]);
  1288. }
  1289. }
  1290. [Theory]
  1291. [InlineData ("A sentence has words.\nLine 2.", 0, -29, Alignment.Start, false, 1, true, new [] { "" })]
  1292. [InlineData (
  1293. "A sentence has words.\nLine 2.",
  1294. 1,
  1295. -28,
  1296. Alignment.Start,
  1297. false,
  1298. 2,
  1299. false,
  1300. new [] { "A", "L" }
  1301. )]
  1302. [InlineData (
  1303. "A sentence has words.\nLine 2.",
  1304. 5,
  1305. -24,
  1306. Alignment.Start,
  1307. false,
  1308. 2,
  1309. false,
  1310. new [] { "A sen", "Line " }
  1311. )]
  1312. [InlineData (
  1313. "A sentence has words.\nLine 2.",
  1314. 28,
  1315. -1,
  1316. Alignment.Start,
  1317. false,
  1318. 2,
  1319. false,
  1320. new [] { "A sentence has words.", "Line 2." }
  1321. )]
  1322. //// no clip
  1323. [InlineData (
  1324. "A sentence has words.\nLine 2.",
  1325. 29,
  1326. 0,
  1327. Alignment.Start,
  1328. false,
  1329. 2,
  1330. false,
  1331. new [] { "A sentence has words.", "Line 2." }
  1332. )]
  1333. [InlineData (
  1334. "A sentence has words.\nLine 2.",
  1335. 30,
  1336. 1,
  1337. Alignment.Start,
  1338. false,
  1339. 2,
  1340. false,
  1341. new [] { "A sentence has words.", "Line 2." }
  1342. )]
  1343. [InlineData ("A sentence has words.\r\nLine 2.", 0, -30, Alignment.Start, false, 1, true, new [] { "" })]
  1344. [InlineData (
  1345. "A sentence has words.\r\nLine 2.",
  1346. 1,
  1347. -29,
  1348. Alignment.Start,
  1349. false,
  1350. 2,
  1351. false,
  1352. new [] { "A", "L" }
  1353. )]
  1354. [InlineData (
  1355. "A sentence has words.\r\nLine 2.",
  1356. 5,
  1357. -25,
  1358. Alignment.Start,
  1359. false,
  1360. 2,
  1361. false,
  1362. new [] { "A sen", "Line " }
  1363. )]
  1364. [InlineData (
  1365. "A sentence has words.\r\nLine 2.",
  1366. 29,
  1367. -1,
  1368. Alignment.Start,
  1369. false,
  1370. 2,
  1371. false,
  1372. new [] { "A sentence has words.", "Line 2." }
  1373. )]
  1374. [InlineData (
  1375. "A sentence has words.\r\nLine 2.",
  1376. 30,
  1377. 0,
  1378. Alignment.Start,
  1379. false,
  1380. 2,
  1381. false,
  1382. new [] { "A sentence has words.", "Line 2." }
  1383. )]
  1384. [InlineData (
  1385. "A sentence has words.\r\nLine 2.",
  1386. 31,
  1387. 1,
  1388. Alignment.Start,
  1389. false,
  1390. 2,
  1391. false,
  1392. new [] { "A sentence has words.", "Line 2." }
  1393. )]
  1394. public void Reformat_NoWordrap_NewLines_MultiLine_True (
  1395. string text,
  1396. int maxWidth,
  1397. int widthOffset,
  1398. Alignment alignment,
  1399. bool wrap,
  1400. int linesCount,
  1401. bool stringEmpty,
  1402. IEnumerable<string> resultLines
  1403. )
  1404. {
  1405. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  1406. List<string> list = TextFormatter.Format (
  1407. text,
  1408. maxWidth,
  1409. alignment,
  1410. wrap,
  1411. false,
  1412. 0,
  1413. TextDirection.LeftRight_TopBottom,
  1414. true
  1415. );
  1416. Assert.NotEmpty (list);
  1417. Assert.True (list.Count == linesCount);
  1418. if (stringEmpty)
  1419. {
  1420. Assert.Equal (string.Empty, list [0]);
  1421. }
  1422. else
  1423. {
  1424. Assert.NotEqual (string.Empty, list [0]);
  1425. }
  1426. Assert.Equal (list, resultLines);
  1427. }
  1428. [Theory]
  1429. [InlineData ("A sentence has words.\nLine 2.", 0, -29, Alignment.Start, false, 1, true, new [] { "" })]
  1430. [InlineData (
  1431. "A sentence has words.\nLine 2.",
  1432. 1,
  1433. -28,
  1434. Alignment.Start,
  1435. false,
  1436. 2,
  1437. false,
  1438. new [] { "A", "L" }
  1439. )]
  1440. [InlineData (
  1441. "A sentence has words.\nLine 2.",
  1442. 5,
  1443. -24,
  1444. Alignment.Start,
  1445. false,
  1446. 2,
  1447. false,
  1448. new [] { "A sen", "Line " }
  1449. )]
  1450. [InlineData (
  1451. "A sentence has words.\nLine 2.",
  1452. 28,
  1453. -1,
  1454. Alignment.Start,
  1455. false,
  1456. 2,
  1457. false,
  1458. new [] { "A sentence has words.", "Line 2." }
  1459. )]
  1460. //// no clip
  1461. [InlineData (
  1462. "A sentence has words.\nLine 2.",
  1463. 29,
  1464. 0,
  1465. Alignment.Start,
  1466. false,
  1467. 2,
  1468. false,
  1469. new [] { "A sentence has words.", "Line 2." }
  1470. )]
  1471. [InlineData (
  1472. "A sentence has words.\nLine 2.",
  1473. 30,
  1474. 1,
  1475. Alignment.Start,
  1476. false,
  1477. 2,
  1478. false,
  1479. new [] { "A sentence has words.", "Line 2." }
  1480. )]
  1481. [InlineData ("A sentence has words.\r\nLine 2.", 0, -30, Alignment.Start, false, 1, true, new [] { "" })]
  1482. [InlineData (
  1483. "A sentence has words.\r\nLine 2.",
  1484. 1,
  1485. -29,
  1486. Alignment.Start,
  1487. false,
  1488. 2,
  1489. false,
  1490. new [] { "A", "L" }
  1491. )]
  1492. [InlineData (
  1493. "A sentence has words.\r\nLine 2.",
  1494. 5,
  1495. -25,
  1496. Alignment.Start,
  1497. false,
  1498. 2,
  1499. false,
  1500. new [] { "A sen", "Line " }
  1501. )]
  1502. [InlineData (
  1503. "A sentence has words.\r\nLine 2.",
  1504. 29,
  1505. -1,
  1506. Alignment.Start,
  1507. false,
  1508. 2,
  1509. false,
  1510. new [] { "A sentence has words.", "Line 2." }
  1511. )]
  1512. [InlineData (
  1513. "A sentence has words.\r\nLine 2.",
  1514. 30,
  1515. 0,
  1516. Alignment.Start,
  1517. false,
  1518. 2,
  1519. false,
  1520. new [] { "A sentence has words.", "Line 2." }
  1521. )]
  1522. [InlineData (
  1523. "A sentence has words.\r\nLine 2.",
  1524. 31,
  1525. 1,
  1526. Alignment.Start,
  1527. false,
  1528. 2,
  1529. false,
  1530. new [] { "A sentence has words.", "Line 2." }
  1531. )]
  1532. public void Reformat_NoWordrap_NewLines_MultiLine_True_Vertical (
  1533. string text,
  1534. int maxWidth,
  1535. int widthOffset,
  1536. Alignment alignment,
  1537. bool wrap,
  1538. int linesCount,
  1539. bool stringEmpty,
  1540. IEnumerable<string> resultLines
  1541. )
  1542. {
  1543. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  1544. List<string> list = TextFormatter.Format (
  1545. text,
  1546. maxWidth,
  1547. alignment,
  1548. wrap,
  1549. false,
  1550. 0,
  1551. TextDirection.TopBottom_LeftRight,
  1552. true
  1553. );
  1554. Assert.NotEmpty (list);
  1555. Assert.True (list.Count == linesCount);
  1556. if (stringEmpty)
  1557. {
  1558. Assert.Equal (string.Empty, list [0]);
  1559. }
  1560. else
  1561. {
  1562. Assert.NotEqual (string.Empty, list [0]);
  1563. }
  1564. Assert.Equal (list, resultLines);
  1565. }
  1566. [Theory]
  1567. [InlineData ("", 0, 0, Alignment.Start, false, 1, true)]
  1568. [InlineData ("", 1, 1, Alignment.Start, false, 1, true)]
  1569. [InlineData ("A sentence has words.", 0, -21, Alignment.Start, false, 1, true)]
  1570. [InlineData ("A sentence has words.", 1, -20, Alignment.Start, false, 1, false)]
  1571. [InlineData ("A sentence has words.", 5, -16, Alignment.Start, false, 1, false)]
  1572. [InlineData ("A sentence has words.", 20, -1, Alignment.Start, false, 1, false)]
  1573. // no clip
  1574. [InlineData ("A sentence has words.", 21, 0, Alignment.Start, false, 1, false)]
  1575. [InlineData ("A sentence has words.", 22, 1, Alignment.Start, false, 1, false)]
  1576. public void Reformat_NoWordrap_SingleLine (
  1577. string text,
  1578. int maxWidth,
  1579. int widthOffset,
  1580. Alignment alignment,
  1581. bool wrap,
  1582. int linesCount,
  1583. bool stringEmpty
  1584. )
  1585. {
  1586. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  1587. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  1588. List<string> list = TextFormatter.Format (text, maxWidth, alignment, wrap);
  1589. Assert.NotEmpty (list);
  1590. Assert.True (list.Count == linesCount);
  1591. if (stringEmpty)
  1592. {
  1593. Assert.Equal (string.Empty, list [0]);
  1594. }
  1595. else
  1596. {
  1597. Assert.NotEqual (string.Empty, list [0]);
  1598. }
  1599. Assert.Equal (StringExtensions.ToString (text.ToRunes () [..expectedClippedWidth]), list [0]);
  1600. }
  1601. [Theory]
  1602. // Unicode
  1603. [InlineData (
  1604. "\u2460\u2461\u2462\n\u2460\u2461\u2462\u2463\u2464",
  1605. 8,
  1606. -1,
  1607. Alignment.Start,
  1608. true,
  1609. false,
  1610. new [] { "\u2460\u2461\u2462", "\u2460\u2461\u2462\u2463\u2464" }
  1611. )]
  1612. // no clip
  1613. [InlineData (
  1614. "\u2460\u2461\u2462\n\u2460\u2461\u2462\u2463\u2464",
  1615. 9,
  1616. 0,
  1617. Alignment.Start,
  1618. true,
  1619. false,
  1620. new [] { "\u2460\u2461\u2462", "\u2460\u2461\u2462\u2463\u2464" }
  1621. )]
  1622. [InlineData (
  1623. "\u2460\u2461\u2462\n\u2460\u2461\u2462\u2463\u2464",
  1624. 10,
  1625. 1,
  1626. Alignment.Start,
  1627. true,
  1628. false,
  1629. new [] { "\u2460\u2461\u2462", "\u2460\u2461\u2462\u2463\u2464" }
  1630. )]
  1631. public void Reformat_Unicode_Wrap_Spaces_NewLines (
  1632. string text,
  1633. int maxWidth,
  1634. int widthOffset,
  1635. Alignment alignment,
  1636. bool wrap,
  1637. bool preserveTrailingSpaces,
  1638. IEnumerable<string> resultLines
  1639. )
  1640. {
  1641. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  1642. List<string> list = TextFormatter.Format (text, maxWidth, alignment, wrap, preserveTrailingSpaces);
  1643. Assert.Equal (list.Count, resultLines.Count ());
  1644. Assert.Equal (resultLines, list);
  1645. }
  1646. [Theory]
  1647. // Unicode
  1648. // Even # of chars
  1649. // 0123456789
  1650. [InlineData ("\u2660пÑРвРÑ", 10, -1, Alignment.Start, true, false, new [] { "\u2660пÑРвÐ", "Ñ" })]
  1651. // no clip
  1652. [InlineData ("\u2660пÑРвРÑ", 11, 0, Alignment.Start, true, false, new [] { "\u2660пÑРвРÑ" })]
  1653. [InlineData ("\u2660пÑРвРÑ", 12, 1, Alignment.Start, true, false, new [] { "\u2660пÑРвРÑ" })]
  1654. // Unicode
  1655. // Odd # of chars
  1656. // 0123456789
  1657. [InlineData ("\u2660 ÑРвРÑ", 9, -1, Alignment.Start, true, false, new [] { "\u2660 ÑРвÐ", "Ñ" })]
  1658. // no clip
  1659. [InlineData ("\u2660 ÑРвРÑ", 10, 0, Alignment.Start, true, false, new [] { "\u2660 ÑРвРÑ" })]
  1660. [InlineData ("\u2660 ÑРвРÑ", 11, 1, Alignment.Start, true, false, new [] { "\u2660 ÑРвРÑ" })]
  1661. public void Reformat_Unicode_Wrap_Spaces_No_NewLines (
  1662. string text,
  1663. int maxWidth,
  1664. int widthOffset,
  1665. Alignment alignment,
  1666. bool wrap,
  1667. bool preserveTrailingSpaces,
  1668. IEnumerable<string> resultLines
  1669. )
  1670. {
  1671. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  1672. List<string> list = TextFormatter.Format (text, maxWidth, alignment, wrap, preserveTrailingSpaces);
  1673. Assert.Equal (list.Count, resultLines.Count ());
  1674. Assert.Equal (resultLines, list);
  1675. }
  1676. [Theory]
  1677. // Even # of spaces
  1678. // 0123456789
  1679. [InlineData ("012 456 89", 0, -10, Alignment.Start, true, true, true, new [] { "" })]
  1680. [InlineData (
  1681. "012 456 89",
  1682. 1,
  1683. -9,
  1684. Alignment.Start,
  1685. true,
  1686. true,
  1687. false,
  1688. new [] { "0", "1", "2", " ", "4", "5", "6", " ", "8", "9" },
  1689. "01245689"
  1690. )]
  1691. [InlineData ("012 456 89", 5, -5, Alignment.Start, true, true, false, new [] { "012 ", "456 ", "89" })]
  1692. [InlineData ("012 456 89", 9, -1, Alignment.Start, true, true, false, new [] { "012 456 ", "89" })]
  1693. // no clip
  1694. [InlineData ("012 456 89", 10, 0, Alignment.Start, true, true, false, new [] { "012 456 89" })]
  1695. [InlineData ("012 456 89", 11, 1, Alignment.Start, true, true, false, new [] { "012 456 89" })]
  1696. // Odd # of spaces
  1697. // 01234567890123
  1698. [InlineData ("012 456 89 end", 13, -1, Alignment.Start, true, true, false, new [] { "012 456 89 ", "end" })]
  1699. // no clip
  1700. [InlineData ("012 456 89 end", 14, 0, Alignment.Start, true, true, false, new [] { "012 456 89 end" })]
  1701. [InlineData ("012 456 89 end", 15, 1, Alignment.Start, true, true, false, new [] { "012 456 89 end" })]
  1702. public void Reformat_Wrap_Spaces_No_NewLines (
  1703. string text,
  1704. int maxWidth,
  1705. int widthOffset,
  1706. Alignment alignment,
  1707. bool wrap,
  1708. bool preserveTrailingSpaces,
  1709. bool stringEmpty,
  1710. IEnumerable<string> resultLines,
  1711. string noSpaceText = ""
  1712. )
  1713. {
  1714. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  1715. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  1716. List<string> list = TextFormatter.Format (text, maxWidth, alignment, wrap, preserveTrailingSpaces);
  1717. Assert.NotEmpty (list);
  1718. Assert.True (list.Count == resultLines.Count ());
  1719. if (stringEmpty)
  1720. {
  1721. Assert.Equal (string.Empty, list [0]);
  1722. }
  1723. else
  1724. {
  1725. Assert.NotEqual (string.Empty, list [0]);
  1726. }
  1727. Assert.Equal (resultLines, list);
  1728. if (maxWidth > 0)
  1729. {
  1730. // remove whitespace chars
  1731. if (maxWidth < 5)
  1732. {
  1733. expectedClippedWidth = text.GetRuneCount () - text.Sum (r => r == ' ' ? 1 : 0);
  1734. }
  1735. else
  1736. {
  1737. expectedClippedWidth = Math.Min (
  1738. text.GetRuneCount (),
  1739. maxWidth - text.Sum (r => r == ' ' ? 1 : 0)
  1740. );
  1741. }
  1742. list = TextFormatter.Format (text, maxWidth, Alignment.Start, wrap);
  1743. if (maxWidth == 1)
  1744. {
  1745. Assert.Equal (expectedClippedWidth, list.Count);
  1746. Assert.Equal (noSpaceText, string.Concat (list.ToArray ()));
  1747. }
  1748. if (maxWidth > 1 && maxWidth < 10)
  1749. {
  1750. Assert.Equal (
  1751. StringExtensions.ToString (text.ToRunes () [..expectedClippedWidth]),
  1752. list [0]
  1753. );
  1754. }
  1755. }
  1756. }
  1757. [Theory]
  1758. [InlineData (null)]
  1759. [InlineData ("")]
  1760. [InlineData ("a")]
  1761. public void RemoveHotKeySpecifier_InValid_ReturnsOriginal (string text)
  1762. {
  1763. var hotKeySpecifier = (Rune)'_';
  1764. if (text == null)
  1765. {
  1766. Assert.Null (TextFormatter.RemoveHotKeySpecifier (text, 0, hotKeySpecifier));
  1767. Assert.Null (TextFormatter.RemoveHotKeySpecifier (text, -1, hotKeySpecifier));
  1768. Assert.Null (TextFormatter.RemoveHotKeySpecifier (text, 100, hotKeySpecifier));
  1769. }
  1770. else
  1771. {
  1772. Assert.Equal (text, TextFormatter.RemoveHotKeySpecifier (text, 0, hotKeySpecifier));
  1773. Assert.Equal (text, TextFormatter.RemoveHotKeySpecifier (text, -1, hotKeySpecifier));
  1774. Assert.Equal (text, TextFormatter.RemoveHotKeySpecifier (text, 100, hotKeySpecifier));
  1775. }
  1776. }
  1777. [Theory]
  1778. [InlineData ("all lower case", 0)]
  1779. [InlineData ("K Before", 0)]
  1780. [InlineData ("aK Second", 1)]
  1781. [InlineData ("Last K", 5)]
  1782. [InlineData ("fter K", 7)]
  1783. [InlineData ("Multiple K and R", 9)]
  1784. [InlineData ("Non-english: Кдать", 13)]
  1785. public void RemoveHotKeySpecifier_Valid_Legacy_ReturnsOriginal (string text, int hotPos)
  1786. {
  1787. var hotKeySpecifier = (Rune)'_';
  1788. Assert.Equal (text, TextFormatter.RemoveHotKeySpecifier (text, hotPos, hotKeySpecifier));
  1789. }
  1790. [Theory]
  1791. [InlineData ("_K Before", 0, "K Before")]
  1792. [InlineData ("a_K Second", 1, "aK Second")]
  1793. [InlineData ("Last _K", 5, "Last K")]
  1794. [InlineData ("After K_", 7, "After K")]
  1795. [InlineData ("Multiple _K and _R", 9, "Multiple K and _R")]
  1796. [InlineData ("Non-english: _Кдать", 13, "Non-english: Кдать")]
  1797. public void RemoveHotKeySpecifier_Valid_ReturnsStripped (string text, int hotPos, string expectedText)
  1798. {
  1799. var hotKeySpecifier = (Rune)'_';
  1800. Assert.Equal (expectedText, TextFormatter.RemoveHotKeySpecifier (text, hotPos, hotKeySpecifier));
  1801. }
  1802. [Theory]
  1803. [InlineData ("test", 0, 't', "test")]
  1804. [InlineData ("test", 1, 'e', "test")]
  1805. [InlineData ("Ok", 0, 'O', "Ok")]
  1806. [InlineData ("[◦ Ok ◦]", 3, 'O', "[◦ Ok ◦]")]
  1807. [InlineData ("^k", 0, '^', "^k")]
  1808. public void ReplaceHotKeyWithTag (string text, int hotPos, uint tag, string expected)
  1809. {
  1810. var tf = new TextFormatter ();
  1811. List<Rune> runes = text.ToRuneList ();
  1812. Rune rune;
  1813. if (Rune.TryGetRuneAt (text, hotPos, out rune))
  1814. {
  1815. Assert.Equal (rune, (Rune)tag);
  1816. }
  1817. string result = TextFormatter.ReplaceHotKeyWithTag (text, hotPos);
  1818. Assert.Equal (result, expected);
  1819. Assert.Equal ((Rune)tag, result.ToRunes () [hotPos]);
  1820. Assert.Equal (text.GetRuneCount (), runes.Count);
  1821. Assert.Equal (text, StringExtensions.ToString (runes));
  1822. }
  1823. [Theory]
  1824. [MemberData (nameof (SplitEnvironmentNewLine))]
  1825. public void SplitNewLine_Ending__With_Or_Without_NewLine_Probably_CRLF (
  1826. string text,
  1827. IEnumerable<string> expected
  1828. )
  1829. {
  1830. List<string> splited = TextFormatter.SplitNewLine (text);
  1831. Assert.Equal (expected, splited);
  1832. }
  1833. [Theory]
  1834. [InlineData (
  1835. "First Line 界\nSecond Line 界\nThird Line 界\n",
  1836. new [] { "First Line 界", "Second Line 界", "Third Line 界", "" }
  1837. )]
  1838. public void SplitNewLine_Ending_With_NewLine_Only_LF (string text, IEnumerable<string> expected)
  1839. {
  1840. List<string> splited = TextFormatter.SplitNewLine (text);
  1841. Assert.Equal (expected, splited);
  1842. }
  1843. [Theory]
  1844. [InlineData (
  1845. "First Line 界\nSecond Line 界\nThird Line 界",
  1846. new [] { "First Line 界", "Second Line 界", "Third Line 界" }
  1847. )]
  1848. public void SplitNewLine_Ending_Without_NewLine_Only_LF (string text, IEnumerable<string> expected)
  1849. {
  1850. List<string> splited = TextFormatter.SplitNewLine (text);
  1851. Assert.Equal (expected, splited);
  1852. }
  1853. [Theory]
  1854. [InlineData ("New Test 你", 10, 10, 20320, 20320, 9, "你")]
  1855. [InlineData ("New Test \U0001d539", 10, 11, 120121, 55349, 9, "𝔹")]
  1856. public void String_Array_Is_Not_Always_Equal_ToRunes_Array (
  1857. string text,
  1858. int runesLength,
  1859. int stringLength,
  1860. int runeValue,
  1861. int stringValue,
  1862. int index,
  1863. string expected
  1864. )
  1865. {
  1866. Rune [] usToRunes = text.ToRunes ();
  1867. Assert.Equal (runesLength, usToRunes.Length);
  1868. Assert.Equal (stringLength, text.Length);
  1869. Assert.Equal (runeValue, usToRunes [index].Value);
  1870. Assert.Equal (stringValue, text [index]);
  1871. Assert.Equal (expected, usToRunes [index].ToString ());
  1872. if (char.IsHighSurrogate (text [index]))
  1873. {
  1874. // Rune array length isn't equal to string array
  1875. Assert.Equal (expected, new string (new [] { text [index], text [index + 1] }));
  1876. }
  1877. else
  1878. {
  1879. // Rune array length is equal to string array
  1880. Assert.Equal (expected, text [index].ToString ());
  1881. }
  1882. }
  1883. [Theory]
  1884. [InlineData (17, 1, TextDirection.LeftRight_TopBottom, 4, "This is a Tab")]
  1885. [InlineData (1, 17, TextDirection.TopBottom_LeftRight, 4, "T\nh\ni\ns\n \ni\ns\n \na\n \n \n \n \n \nT\na\nb")]
  1886. [InlineData (13, 1, TextDirection.LeftRight_TopBottom, 0, "This is a Tab")]
  1887. [InlineData (1, 13, TextDirection.TopBottom_LeftRight, 0, "T\nh\ni\ns\n \ni\ns\n \na\n \nT\na\nb")]
  1888. public void TabWith_PreserveTrailingSpaces_False (
  1889. int width,
  1890. int height,
  1891. TextDirection textDirection,
  1892. int tabWidth,
  1893. string expected
  1894. )
  1895. {
  1896. var driver = new FakeDriver ();
  1897. driver.Init ();
  1898. var text = "This is a \tTab";
  1899. var tf = new TextFormatter ();
  1900. tf.AutoSize = true;
  1901. tf.Direction = textDirection;
  1902. tf.TabWidth = tabWidth;
  1903. tf.Text = text;
  1904. Assert.True (tf.WordWrap);
  1905. Assert.False (tf.PreserveTrailingSpaces);
  1906. Assert.Equal (new (width, height), tf.Size);
  1907. tf.Draw (
  1908. new (0, 0, width, height),
  1909. new Attribute (ColorName.White, ColorName.Black),
  1910. new Attribute (ColorName.Blue, ColorName.Black),
  1911. default (Rectangle),
  1912. driver
  1913. );
  1914. TestHelpers.AssertDriverContentsWithFrameAre (expected, _output, driver);
  1915. driver.End ();
  1916. }
  1917. [Theory]
  1918. [InlineData (17, 1, TextDirection.LeftRight_TopBottom, 4, "This is a Tab")]
  1919. [InlineData (1, 17, TextDirection.TopBottom_LeftRight, 4, "T\nh\ni\ns\n \ni\ns\n \na\n \n \n \n \n \nT\na\nb")]
  1920. [InlineData (13, 1, TextDirection.LeftRight_TopBottom, 0, "This is a Tab")]
  1921. [InlineData (1, 13, TextDirection.TopBottom_LeftRight, 0, "T\nh\ni\ns\n \ni\ns\n \na\n \nT\na\nb")]
  1922. public void TabWith_PreserveTrailingSpaces_True (
  1923. int width,
  1924. int height,
  1925. TextDirection textDirection,
  1926. int tabWidth,
  1927. string expected
  1928. )
  1929. {
  1930. var driver = new FakeDriver ();
  1931. driver.Init ();
  1932. var text = "This is a \tTab";
  1933. var tf = new TextFormatter ();
  1934. tf.AutoSize = true;
  1935. tf.Direction = textDirection;
  1936. tf.TabWidth = tabWidth;
  1937. tf.PreserveTrailingSpaces = true;
  1938. tf.Text = text;
  1939. Assert.True (tf.WordWrap);
  1940. Assert.Equal (new (width, height), tf.Size);
  1941. tf.Draw (
  1942. new (0, 0, width, height),
  1943. new Attribute (ColorName.White, ColorName.Black),
  1944. new Attribute (ColorName.Blue, ColorName.Black),
  1945. default (Rectangle),
  1946. driver
  1947. );
  1948. TestHelpers.AssertDriverContentsWithFrameAre (expected, _output, driver);
  1949. driver.End ();
  1950. }
  1951. [Theory]
  1952. [InlineData (17, 1, TextDirection.LeftRight_TopBottom, 4, "This is a Tab")]
  1953. [InlineData (1, 17, TextDirection.TopBottom_LeftRight, 4, "T\nh\ni\ns\n \ni\ns\n \na\n \n \n \n \n \nT\na\nb")]
  1954. [InlineData (13, 1, TextDirection.LeftRight_TopBottom, 0, "This is a Tab")]
  1955. [InlineData (1, 13, TextDirection.TopBottom_LeftRight, 0, "T\nh\ni\ns\n \ni\ns\n \na\n \nT\na\nb")]
  1956. public void TabWith_WordWrap_True (
  1957. int width,
  1958. int height,
  1959. TextDirection textDirection,
  1960. int tabWidth,
  1961. string expected
  1962. )
  1963. {
  1964. var driver = new FakeDriver ();
  1965. driver.Init ();
  1966. var text = "This is a \tTab";
  1967. var tf = new TextFormatter ();
  1968. tf.AutoSize = true;
  1969. tf.Direction = textDirection;
  1970. tf.TabWidth = tabWidth;
  1971. tf.WordWrap = true;
  1972. tf.Text = text;
  1973. Assert.False (tf.PreserveTrailingSpaces);
  1974. Assert.Equal (new (width, height), tf.Size);
  1975. tf.Draw (
  1976. new (0, 0, width, height),
  1977. new Attribute (ColorName.White, ColorName.Black),
  1978. new Attribute (ColorName.Blue, ColorName.Black),
  1979. default (Rectangle),
  1980. driver
  1981. );
  1982. TestHelpers.AssertDriverContentsWithFrameAre (expected, _output, driver);
  1983. driver.End ();
  1984. }
  1985. [Theory]
  1986. [InlineData ("123456789", 3, "123")]
  1987. [InlineData ("Hello World", 8, "Hello Wo")]
  1988. public void TestClipOrPad_LongWord (string text, int fillPad, string expectedText)
  1989. {
  1990. // word is long but we want it to fill # space only
  1991. Assert.Equal (expectedText, TextFormatter.ClipOrPad (text, fillPad));
  1992. }
  1993. [Theory]
  1994. [InlineData ("fff", 6, "fff ")]
  1995. [InlineData ("Hello World", 16, "Hello World ")]
  1996. public void TestClipOrPad_ShortWord (string text, int fillPad, string expectedText)
  1997. {
  1998. // word is short but we want it to fill # so it should be padded
  1999. Assert.Equal (expectedText, TextFormatter.ClipOrPad (text, fillPad));
  2000. }
  2001. [Theory]
  2002. [InlineData ("你你", TextDirection.LeftRight_TopBottom, 4, 1)]
  2003. [InlineData ("AB", TextDirection.LeftRight_TopBottom, 2, 1)]
  2004. [InlineData ("你你", TextDirection.TopBottom_LeftRight, 2, 2)]
  2005. [InlineData ("AB", TextDirection.TopBottom_LeftRight, 1, 2)]
  2006. public void AutoSize_True_TextDirection_Correct_Size (string text, TextDirection textDirection, int expectedWidth, int expectedHeight)
  2007. {
  2008. var tf = new TextFormatter { Direction = textDirection, Text = text };
  2009. Assert.False (tf.AutoSize);
  2010. // If autosize is false, no auto sizing!
  2011. Assert.Equal (Size.Empty, tf.Size);
  2012. tf.Size = new (1, 1); // This should have no impact (autosize overrides)
  2013. tf.AutoSize = true;
  2014. Assert.Equal (new Size (expectedWidth, expectedHeight), tf.Size);
  2015. }
  2016. [Theory]
  2017. [InlineData ("你", TextDirection.LeftRight_TopBottom, false, 0, 0)]
  2018. [InlineData ("你", TextDirection.LeftRight_TopBottom, true, 2, 1)]
  2019. [InlineData ("你", TextDirection.TopBottom_LeftRight, false, 0, 0)]
  2020. [InlineData ("你", TextDirection.TopBottom_LeftRight, true, 2, 1)]
  2021. [InlineData ("你你", TextDirection.LeftRight_TopBottom, false, 0, 0)]
  2022. [InlineData ("你你", TextDirection.LeftRight_TopBottom, true, 4, 1)]
  2023. [InlineData ("你你", TextDirection.TopBottom_LeftRight, false, 0, 0)]
  2024. [InlineData ("你你", TextDirection.TopBottom_LeftRight, true, 2, 2)]
  2025. public void Text_Set_SizeIsCorrect (string text, TextDirection textDirection, bool autoSize, int expectedWidth, int expectedHeight)
  2026. {
  2027. var tf = new TextFormatter { Direction = textDirection, Text = text, AutoSize = autoSize };
  2028. Assert.Equal (new Size (expectedWidth, expectedHeight), tf.Size);
  2029. }
  2030. [Fact]
  2031. public void WordWrap_BigWidth ()
  2032. {
  2033. List<string> wrappedLines;
  2034. var text = "Constantinople";
  2035. wrappedLines = TextFormatter.WordWrapText (text, 100);
  2036. Assert.True (wrappedLines.Count == 1);
  2037. Assert.Equal ("Constantinople", wrappedLines [0]);
  2038. }
  2039. [Fact]
  2040. public void WordWrap_Invalid ()
  2041. {
  2042. var text = string.Empty;
  2043. var width = 0;
  2044. Assert.Empty (TextFormatter.WordWrapText (null, width));
  2045. Assert.Empty (TextFormatter.WordWrapText (text, width));
  2046. Assert.Throws<ArgumentOutOfRangeException> (() => TextFormatter.WordWrapText (text, -1));
  2047. }
  2048. [Theory]
  2049. [InlineData ("A sentence has words.", 3, -18, new [] { "A", "sen", "ten", "ce", "has", "wor", "ds." })]
  2050. [InlineData (
  2051. "A sentence has words.",
  2052. 2,
  2053. -19,
  2054. new [] { "A", "se", "nt", "en", "ce", "ha", "s", "wo", "rd", "s." }
  2055. )]
  2056. [InlineData (
  2057. "A sentence has words.",
  2058. 1,
  2059. -20,
  2060. new [] { "A", "s", "e", "n", "t", "e", "n", "c", "e", "h", "a", "s", "w", "o", "r", "d", "s", "." }
  2061. )]
  2062. public void WordWrap_Narrow_Default (
  2063. string text,
  2064. int maxWidth,
  2065. int widthOffset,
  2066. IEnumerable<string> resultLines
  2067. )
  2068. {
  2069. // Calls WordWrapText (text, width) and thus preserveTrailingSpaces defaults to false
  2070. List<string> wrappedLines;
  2071. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2072. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2073. wrappedLines = TextFormatter.WordWrapText (text, maxWidth);
  2074. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2075. Assert.True (
  2076. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2077. );
  2078. Assert.True (
  2079. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2080. );
  2081. Assert.Equal (resultLines, wrappedLines);
  2082. }
  2083. [Theory]
  2084. [InlineData ("A sentence has words.", 21, 0, new [] { "A sentence has words." })]
  2085. [InlineData ("A sentence has words.", 20, -1, new [] { "A sentence has", "words." })]
  2086. [InlineData ("A sentence has words.", 15, -6, new [] { "A sentence has", "words." })]
  2087. [InlineData ("A sentence has words.", 14, -7, new [] { "A sentence has", "words." })]
  2088. [InlineData ("A sentence has words.", 13, -8, new [] { "A sentence", "has words." })]
  2089. // Unicode
  2090. [InlineData (
  2091. "A Unicode sentence (пÑивеÑ) has words.",
  2092. 42,
  2093. 0,
  2094. new [] { "A Unicode sentence (пÑивеÑ) has words." }
  2095. )]
  2096. [InlineData (
  2097. "A Unicode sentence (пÑивеÑ) has words.",
  2098. 41,
  2099. -1,
  2100. new [] { "A Unicode sentence (пÑивеÑ) has", "words." }
  2101. )]
  2102. [InlineData (
  2103. "A Unicode sentence (пÑивеÑ) has words.",
  2104. 36,
  2105. -6,
  2106. new [] { "A Unicode sentence (пÑивеÑ) has", "words." }
  2107. )]
  2108. [InlineData (
  2109. "A Unicode sentence (пÑивеÑ) has words.",
  2110. 35,
  2111. -7,
  2112. new [] { "A Unicode sentence (пÑивеÑ) has", "words." }
  2113. )]
  2114. [InlineData (
  2115. "A Unicode sentence (пÑивеÑ) has words.",
  2116. 34,
  2117. -8,
  2118. new [] { "A Unicode sentence (пÑивеÑ)", "has words." }
  2119. )]
  2120. [InlineData (
  2121. "A Unicode sentence (пÑивеÑ) has words.",
  2122. 25,
  2123. -17,
  2124. new [] { "A Unicode sentence", "(пÑивеÑ) has words." }
  2125. )]
  2126. public void WordWrap_NoNewLines_Default (
  2127. string text,
  2128. int maxWidth,
  2129. int widthOffset,
  2130. IEnumerable<string> resultLines
  2131. )
  2132. {
  2133. // Calls WordWrapText (text, width) and thus preserveTrailingSpaces defaults to false
  2134. List<string> wrappedLines;
  2135. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2136. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2137. wrappedLines = TextFormatter.WordWrapText (text, maxWidth);
  2138. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2139. Assert.True (
  2140. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2141. );
  2142. Assert.True (
  2143. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2144. );
  2145. Assert.Equal (resultLines, wrappedLines);
  2146. }
  2147. [Theory]
  2148. [InlineData ("これが最初の行です。 こんにちは世界。 これが2行目です。", 29, 0, new [] { "これが最初の行です。", "こんにちは世界。", "これが2行目です。" })]
  2149. public void WordWrap_PreserveTrailingSpaces_False_Unicode_Wide_Runes (
  2150. string text,
  2151. int maxWidth,
  2152. int widthOffset,
  2153. IEnumerable<string> resultLines
  2154. )
  2155. {
  2156. List<string> wrappedLines;
  2157. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2158. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2159. wrappedLines = TextFormatter.WordWrapText (text, maxWidth);
  2160. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2161. Assert.True (
  2162. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2163. );
  2164. Assert.True (
  2165. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2166. );
  2167. Assert.Equal (resultLines, wrappedLines);
  2168. }
  2169. [Theory]
  2170. [InlineData ("文に は言葉 があり ます。", 14, 0, new [] { "文に は言葉", "があり ます。" })]
  2171. [InlineData ("文に は言葉 があり ます。", 3, -11, new [] { "文", "に", "は", "言", "葉", "が", "あ", "り", "ま", "す", "。" })]
  2172. [InlineData ("文に は言葉 があり ます。", 2, -12, new [] { "文", "に", "は", "言", "葉", "が", "あ", "り", "ま", "す", "。" })]
  2173. [InlineData (
  2174. "文に は言葉 があり ます。",
  2175. 1,
  2176. -13,
  2177. new [] { " ", " ", " " }
  2178. )] // Just Spaces; should result in a single space for each line
  2179. public void WordWrap_PreserveTrailingSpaces_False_Wide_Runes (
  2180. string text,
  2181. int maxWidth,
  2182. int widthOffset,
  2183. IEnumerable<string> resultLines
  2184. )
  2185. {
  2186. List<string> wrappedLines;
  2187. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2188. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2189. wrappedLines = TextFormatter.WordWrapText (text, maxWidth);
  2190. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2191. Assert.True (
  2192. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2193. );
  2194. Assert.True (
  2195. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2196. );
  2197. Assert.Equal (resultLines, wrappedLines);
  2198. }
  2199. [Theory]
  2200. [InlineData (null, 1, new string [] { })] // null input
  2201. [InlineData ("", 1, new string [] { })] // Empty input
  2202. [InlineData ("1 34", 1, new [] { "1", "3", "4" })] // Single Spaces
  2203. [InlineData ("1", 1, new [] { "1" })] // Short input
  2204. [InlineData ("12", 1, new [] { "1", "2" })]
  2205. [InlineData ("123", 1, new [] { "1", "2", "3" })]
  2206. [InlineData ("123456", 1, new [] { "1", "2", "3", "4", "5", "6" })] // No spaces
  2207. [InlineData (" ", 1, new [] { " " })] // Just Spaces; should result in a single space
  2208. [InlineData (" ", 1, new [] { " " })]
  2209. [InlineData (" ", 1, new [] { " ", " " })]
  2210. [InlineData (" ", 1, new [] { " ", " " })]
  2211. [InlineData ("12 456", 1, new [] { "1", "2", "4", "5", "6" })] // Single Spaces
  2212. [InlineData (" 2 456", 1, new [] { " ", "2", "4", "5", "6" })] // Leading spaces should be preserved.
  2213. [InlineData (" 2 456 8", 1, new [] { " ", "2", "4", "5", "6", "8" })]
  2214. [InlineData (
  2215. "A sentence has words. ",
  2216. 1,
  2217. new [] { "A", "s", "e", "n", "t", "e", "n", "c", "e", "h", "a", "s", "w", "o", "r", "d", "s", "." }
  2218. )] // Complex example
  2219. [InlineData ("12 567", 1, new [] { "1", "2", " ", "5", "6", "7" })] // Double Spaces
  2220. [InlineData (" 3 567", 1, new [] { " ", "3", "5", "6", "7" })] // Double Leading spaces should be preserved.
  2221. [InlineData (" 3 678 1", 1, new [] { " ", "3", " ", "6", "7", "8", " ", "1" })]
  2222. [InlineData ("1 456", 1, new [] { "1", " ", "4", "5", "6" })]
  2223. [InlineData (
  2224. "A sentence has words. ",
  2225. 1,
  2226. new []
  2227. {
  2228. "A", " ", "s", "e", "n", "t", "e", "n", "c", "e", " ", "h", "a", "s", "w", "o", "r", "d", "s", ".", " "
  2229. }
  2230. )] // Double space Complex example
  2231. public void WordWrap_PreserveTrailingSpaces_False_With_Simple_Runes_Width_1 (
  2232. string text,
  2233. int width,
  2234. IEnumerable<string> resultLines
  2235. )
  2236. {
  2237. List<string> wrappedLines = TextFormatter.WordWrapText (text, width);
  2238. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2239. Assert.Equal (resultLines, wrappedLines);
  2240. var breakLines = "";
  2241. foreach (string line in wrappedLines)
  2242. {
  2243. breakLines += $"{line}{Environment.NewLine}";
  2244. }
  2245. var expected = string.Empty;
  2246. foreach (string line in resultLines)
  2247. {
  2248. expected += $"{line}{Environment.NewLine}";
  2249. }
  2250. Assert.Equal (expected, breakLines);
  2251. }
  2252. [Theory]
  2253. [InlineData (null, 3, new string [] { })] // null input
  2254. [InlineData ("", 3, new string [] { })] // Empty input
  2255. [InlineData ("1", 3, new [] { "1" })] // Short input
  2256. [InlineData ("12", 3, new [] { "12" })]
  2257. [InlineData ("123", 3, new [] { "123" })]
  2258. [InlineData ("123456", 3, new [] { "123", "456" })] // No spaces
  2259. [InlineData ("1234567", 3, new [] { "123", "456", "7" })] // No spaces
  2260. [InlineData (" ", 3, new [] { " " })] // Just Spaces; should result in a single space
  2261. [InlineData (" ", 3, new [] { " " })]
  2262. [InlineData (" ", 3, new [] { " " })]
  2263. [InlineData (" ", 3, new [] { " " })]
  2264. [InlineData ("12 456", 3, new [] { "12", "456" })] // Single Spaces
  2265. [InlineData (" 2 456", 3, new [] { " 2", "456" })] // Leading spaces should be preserved.
  2266. [InlineData (" 2 456 8", 3, new [] { " 2", "456", "8" })]
  2267. [InlineData (
  2268. "A sentence has words. ",
  2269. 3,
  2270. new [] { "A", "sen", "ten", "ce", "has", "wor", "ds." }
  2271. )] // Complex example
  2272. [InlineData ("12 567", 3, new [] { "12 ", "567" })] // Double Spaces
  2273. [InlineData (" 3 567", 3, new [] { " 3", "567" })] // Double Leading spaces should be preserved.
  2274. [InlineData (" 3 678 1", 3, new [] { " 3", " 67", "8 ", "1" })]
  2275. [InlineData ("1 456", 3, new [] { "1 ", "456" })]
  2276. [InlineData (
  2277. "A sentence has words. ",
  2278. 3,
  2279. new [] { "A ", "sen", "ten", "ce ", " ", "has", "wor", "ds.", " " }
  2280. )] // Double space Complex example
  2281. public void WordWrap_PreserveTrailingSpaces_False_With_Simple_Runes_Width_3 (
  2282. string text,
  2283. int width,
  2284. IEnumerable<string> resultLines
  2285. )
  2286. {
  2287. List<string> wrappedLines = TextFormatter.WordWrapText (text, width);
  2288. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2289. Assert.Equal (resultLines, wrappedLines);
  2290. var breakLines = "";
  2291. foreach (string line in wrappedLines)
  2292. {
  2293. breakLines += $"{line}{Environment.NewLine}";
  2294. }
  2295. var expected = string.Empty;
  2296. foreach (string line in resultLines)
  2297. {
  2298. expected += $"{line}{Environment.NewLine}";
  2299. }
  2300. Assert.Equal (expected, breakLines);
  2301. }
  2302. [Theory]
  2303. [InlineData (null, 50, new string [] { })] // null input
  2304. [InlineData ("", 50, new string [] { })] // Empty input
  2305. [InlineData ("1", 50, new [] { "1" })] // Short input
  2306. [InlineData ("12", 50, new [] { "12" })]
  2307. [InlineData ("123", 50, new [] { "123" })]
  2308. [InlineData ("123456", 50, new [] { "123456" })] // No spaces
  2309. [InlineData ("1234567", 50, new [] { "1234567" })] // No spaces
  2310. [InlineData (" ", 50, new [] { " " })] // Just Spaces; should result in a single space
  2311. [InlineData (" ", 50, new [] { " " })]
  2312. [InlineData (" ", 50, new [] { " " })]
  2313. [InlineData ("12 456", 50, new [] { "12 456" })] // Single Spaces
  2314. [InlineData (" 2 456", 50, new [] { " 2 456" })] // Leading spaces should be preserved.
  2315. [InlineData (" 2 456 8", 50, new [] { " 2 456 8" })]
  2316. [InlineData ("A sentence has words. ", 50, new [] { "A sentence has words. " })] // Complex example
  2317. [InlineData ("12 567", 50, new [] { "12 567" })] // Double Spaces
  2318. [InlineData (" 3 567", 50, new [] { " 3 567" })] // Double Leading spaces should be preserved.
  2319. [InlineData (" 3 678 1", 50, new [] { " 3 678 1" })]
  2320. [InlineData ("1 456", 50, new [] { "1 456" })]
  2321. [InlineData (
  2322. "A sentence has words. ",
  2323. 50,
  2324. new [] { "A sentence has words. " }
  2325. )] // Double space Complex example
  2326. public void WordWrap_PreserveTrailingSpaces_False_With_Simple_Runes_Width_50 (
  2327. string text,
  2328. int width,
  2329. IEnumerable<string> resultLines
  2330. )
  2331. {
  2332. List<string> wrappedLines = TextFormatter.WordWrapText (text, width);
  2333. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2334. Assert.Equal (resultLines, wrappedLines);
  2335. var breakLines = "";
  2336. foreach (string line in wrappedLines)
  2337. {
  2338. breakLines += $"{line}{Environment.NewLine}";
  2339. }
  2340. var expected = string.Empty;
  2341. foreach (string line in resultLines)
  2342. {
  2343. expected += $"{line}{Environment.NewLine}";
  2344. }
  2345. Assert.Equal (expected, breakLines);
  2346. }
  2347. [Theory]
  2348. [InlineData ("A sentence has words.", 14, -7, new [] { "A sentence ", "has words." })]
  2349. [InlineData ("A sentence has words.", 8, -13, new [] { "A ", "sentence", " has ", "words." })]
  2350. [InlineData ("A sentence has words.", 6, -15, new [] { "A ", "senten", "ce ", "has ", "words." })]
  2351. [InlineData ("A sentence has words.", 3, -18, new [] { "A ", "sen", "ten", "ce ", "has", " ", "wor", "ds." })]
  2352. [InlineData (
  2353. "A sentence has words.",
  2354. 2,
  2355. -19,
  2356. new [] { "A ", "se", "nt", "en", "ce", " ", "ha", "s ", "wo", "rd", "s." }
  2357. )]
  2358. [InlineData (
  2359. "A sentence has words.",
  2360. 1,
  2361. -20,
  2362. new []
  2363. {
  2364. "A", " ", "s", "e", "n", "t", "e", "n", "c", "e", " ", "h", "a", "s", " ", "w", "o", "r", "d", "s", "."
  2365. }
  2366. )]
  2367. public void WordWrap_PreserveTrailingSpaces_True (
  2368. string text,
  2369. int maxWidth,
  2370. int widthOffset,
  2371. IEnumerable<string> resultLines
  2372. )
  2373. {
  2374. List<string> wrappedLines;
  2375. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2376. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2377. wrappedLines = TextFormatter.WordWrapText (text, maxWidth, true);
  2378. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2379. Assert.True (
  2380. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2381. );
  2382. Assert.True (
  2383. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2384. );
  2385. Assert.Equal (resultLines, wrappedLines);
  2386. }
  2387. [Theory]
  2388. [InlineData ("文に は言葉 があり ます。", 14, 0, new [] { "文に は言葉 ", "があり ます。" })]
  2389. [InlineData ("文に は言葉 があり ます。", 3, -11, new [] { "文", "に ", "は", "言", "葉 ", "が", "あ", "り ", "ま", "す", "。" })]
  2390. [InlineData (
  2391. "文に は言葉 があり ます。",
  2392. 2,
  2393. -12,
  2394. new [] { "文", "に", " ", "は", "言", "葉", " ", "が", "あ", "り", " ", "ま", "す", "。" }
  2395. )]
  2396. [InlineData ("文に は言葉 があり ます。", 1, -13, new string [] { })]
  2397. public void WordWrap_PreserveTrailingSpaces_True_Wide_Runes (
  2398. string text,
  2399. int maxWidth,
  2400. int widthOffset,
  2401. IEnumerable<string> resultLines
  2402. )
  2403. {
  2404. List<string> wrappedLines;
  2405. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2406. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2407. wrappedLines = TextFormatter.WordWrapText (text, maxWidth, true);
  2408. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2409. Assert.True (
  2410. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2411. );
  2412. Assert.True (
  2413. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2414. );
  2415. Assert.Equal (resultLines, wrappedLines);
  2416. }
  2417. [Theory]
  2418. [InlineData ("A sentence has words. ", 3, new [] { "A ", "sen", "ten", "ce ", "has", " ", "wor", "ds.", " " })]
  2419. [InlineData (
  2420. "A sentence has words. ",
  2421. 3,
  2422. new [] { "A ", " ", "sen", "ten", "ce ", " ", " ", " ", "has", " ", "wor", "ds.", " " }
  2423. )]
  2424. public void WordWrap_PreserveTrailingSpaces_True_With_Simple_Runes_Width_3 (
  2425. string text,
  2426. int width,
  2427. IEnumerable<string> resultLines
  2428. )
  2429. {
  2430. List<string> wrappedLines = TextFormatter.WordWrapText (text, width, true);
  2431. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2432. Assert.Equal (resultLines, wrappedLines);
  2433. var breakLines = "";
  2434. foreach (string line in wrappedLines)
  2435. {
  2436. breakLines += $"{line}{Environment.NewLine}";
  2437. }
  2438. var expected = string.Empty;
  2439. foreach (string line in resultLines)
  2440. {
  2441. expected += $"{line}{Environment.NewLine}";
  2442. }
  2443. Assert.Equal (expected, breakLines);
  2444. // Double space Complex example - this is how VS 2022 does it
  2445. //text = "A sentence has words. ";
  2446. //breakLines = "";
  2447. //wrappedLines = TextFormatter.WordWrapText (text, width, preserveTrailingSpaces: true);
  2448. //foreach (var line in wrappedLines) {
  2449. // breakLines += $"{line}{Environment.NewLine}";
  2450. //}
  2451. //expected = "A " + Environment.NewLine +
  2452. // " se" + Environment.NewLine +
  2453. // " nt" + Environment.NewLine +
  2454. // " en" + Environment.NewLine +
  2455. // " ce" + Environment.NewLine +
  2456. // " " + Environment.NewLine +
  2457. // " " + Environment.NewLine +
  2458. // " " + Environment.NewLine +
  2459. // " ha" + Environment.NewLine +
  2460. // " s " + Environment.NewLine +
  2461. // " wo" + Environment.NewLine +
  2462. // " rd" + Environment.NewLine +
  2463. // " s." + Environment.NewLine;
  2464. //Assert.Equal (expected, breakLines);
  2465. }
  2466. [Theory]
  2467. [InlineData ("A sentence\t\t\t has words.", 14, -10, new [] { "A sentence\t", "\t\t has ", "words." })]
  2468. [InlineData (
  2469. "A sentence\t\t\t has words.",
  2470. 8,
  2471. -16,
  2472. new [] { "A ", "sentence", "\t\t", "\t ", "has ", "words." }
  2473. )]
  2474. [InlineData (
  2475. "A sentence\t\t\t has words.",
  2476. 3,
  2477. -21,
  2478. new [] { "A ", "sen", "ten", "ce", "\t", "\t", "\t", " ", "has", " ", "wor", "ds." }
  2479. )]
  2480. [InlineData (
  2481. "A sentence\t\t\t has words.",
  2482. 2,
  2483. -22,
  2484. new [] { "A ", "se", "nt", "en", "ce", "\t", "\t", "\t", " ", "ha", "s ", "wo", "rd", "s." }
  2485. )]
  2486. [InlineData (
  2487. "A sentence\t\t\t has words.",
  2488. 1,
  2489. -23,
  2490. new []
  2491. {
  2492. "A",
  2493. " ",
  2494. "s",
  2495. "e",
  2496. "n",
  2497. "t",
  2498. "e",
  2499. "n",
  2500. "c",
  2501. "e",
  2502. "\t",
  2503. "\t",
  2504. "\t",
  2505. " ",
  2506. "h",
  2507. "a",
  2508. "s",
  2509. " ",
  2510. "w",
  2511. "o",
  2512. "r",
  2513. "d",
  2514. "s",
  2515. "."
  2516. }
  2517. )]
  2518. public void WordWrap_PreserveTrailingSpaces_True_With_Tab (
  2519. string text,
  2520. int maxWidth,
  2521. int widthOffset,
  2522. IEnumerable<string> resultLines,
  2523. int tabWidth = 4
  2524. )
  2525. {
  2526. List<string> wrappedLines;
  2527. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2528. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2529. wrappedLines = TextFormatter.WordWrapText (text, maxWidth, true, tabWidth);
  2530. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2531. Assert.True (
  2532. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2533. );
  2534. Assert.True (
  2535. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2536. );
  2537. Assert.Equal (resultLines, wrappedLines);
  2538. }
  2539. [Theory]
  2540. [InlineData ("Constantinople", 14, 0, new [] { "Constantinople" })]
  2541. [InlineData ("Constantinople", 12, -2, new [] { "Constantinop", "le" })]
  2542. [InlineData ("Constantinople", 9, -5, new [] { "Constanti", "nople" })]
  2543. [InlineData ("Constantinople", 7, -7, new [] { "Constan", "tinople" })]
  2544. [InlineData ("Constantinople", 5, -9, new [] { "Const", "antin", "ople" })]
  2545. [InlineData ("Constantinople", 4, -10, new [] { "Cons", "tant", "inop", "le" })]
  2546. [InlineData (
  2547. "Constantinople",
  2548. 1,
  2549. -13,
  2550. new [] { "C", "o", "n", "s", "t", "a", "n", "t", "i", "n", "o", "p", "l", "e" }
  2551. )]
  2552. public void WordWrap_SingleWordLine (
  2553. string text,
  2554. int maxWidth,
  2555. int widthOffset,
  2556. IEnumerable<string> resultLines
  2557. )
  2558. {
  2559. List<string> wrappedLines;
  2560. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2561. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2562. wrappedLines = TextFormatter.WordWrapText (text, maxWidth);
  2563. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2564. Assert.True (
  2565. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2566. );
  2567. Assert.True (
  2568. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2569. );
  2570. Assert.Equal (resultLines, wrappedLines);
  2571. }
  2572. [Theory]
  2573. [InlineData ("This\u00A0is\n\u00A0a\u00A0sentence.", 20, 0, new [] { "This\u00A0is\u00A0a\u00A0sentence." })]
  2574. [InlineData ("This\u00A0is\n\u00A0a\u00A0sentence.", 19, -1, new [] { "This\u00A0is\u00A0a\u00A0sentence." })]
  2575. [InlineData (
  2576. "\u00A0\u00A0\u00A0\u00A0\u00A0test\u00A0sentence.",
  2577. 19,
  2578. 0,
  2579. new [] { "\u00A0\u00A0\u00A0\u00A0\u00A0test\u00A0sentence." }
  2580. )]
  2581. public void WordWrap_Unicode_2LinesWithNonBreakingSpace (
  2582. string text,
  2583. int maxWidth,
  2584. int widthOffset,
  2585. IEnumerable<string> resultLines
  2586. )
  2587. {
  2588. List<string> wrappedLines;
  2589. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2590. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2591. wrappedLines = TextFormatter.WordWrapText (text, maxWidth);
  2592. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2593. Assert.True (
  2594. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2595. );
  2596. Assert.True (
  2597. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2598. );
  2599. Assert.Equal (resultLines, wrappedLines);
  2600. }
  2601. [Theory]
  2602. [InlineData ("This\u00A0is\u00A0a\u00A0sentence.", 19, 0, new [] { "This\u00A0is\u00A0a\u00A0sentence." })]
  2603. [InlineData ("This\u00A0is\u00A0a\u00A0sentence.", 18, -1, new [] { "This\u00A0is\u00A0a\u00A0sentence", "." })]
  2604. [InlineData ("This\u00A0is\u00A0a\u00A0sentence.", 17, -2, new [] { "This\u00A0is\u00A0a\u00A0sentenc", "e." })]
  2605. [InlineData ("This\u00A0is\u00A0a\u00A0sentence.", 14, -5, new [] { "This\u00A0is\u00A0a\u00A0sent", "ence." })]
  2606. [InlineData ("This\u00A0is\u00A0a\u00A0sentence.", 10, -9, new [] { "This\u00A0is\u00A0a\u00A0", "sentence." })]
  2607. [InlineData (
  2608. "This\u00A0is\u00A0a\u00A0sentence.",
  2609. 7,
  2610. -12,
  2611. new [] { "This\u00A0is", "\u00A0a\u00A0sent", "ence." }
  2612. )]
  2613. [InlineData (
  2614. "This\u00A0is\u00A0a\u00A0sentence.",
  2615. 5,
  2616. -14,
  2617. new [] { "This\u00A0", "is\u00A0a\u00A0", "sente", "nce." }
  2618. )]
  2619. [InlineData (
  2620. "This\u00A0is\u00A0a\u00A0sentence.",
  2621. 1,
  2622. -18,
  2623. new []
  2624. {
  2625. "T", "h", "i", "s", "\u00A0", "i", "s", "\u00A0", "a", "\u00A0", "s", "e", "n", "t", "e", "n", "c", "e", "."
  2626. }
  2627. )]
  2628. public void WordWrap_Unicode_LineWithNonBreakingSpace (
  2629. string text,
  2630. int maxWidth,
  2631. int widthOffset,
  2632. IEnumerable<string> resultLines
  2633. )
  2634. {
  2635. List<string> wrappedLines;
  2636. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2637. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2638. wrappedLines = TextFormatter.WordWrapText (text, maxWidth);
  2639. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2640. Assert.True (
  2641. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2642. );
  2643. Assert.True (
  2644. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2645. );
  2646. Assert.Equal (resultLines, wrappedLines);
  2647. }
  2648. [Theory]
  2649. [InlineData (
  2650. "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ",
  2651. 51,
  2652. 0,
  2653. new [] { "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ" }
  2654. )]
  2655. [InlineData (
  2656. "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ",
  2657. 50,
  2658. -1,
  2659. new [] { "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ" }
  2660. )]
  2661. [InlineData (
  2662. "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ",
  2663. 46,
  2664. -5,
  2665. new [] { "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮ", "ฯะัาำ" }
  2666. )]
  2667. [InlineData (
  2668. "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ",
  2669. 26,
  2670. -25,
  2671. new [] { "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบ", "ปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ" }
  2672. )]
  2673. [InlineData (
  2674. "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ",
  2675. 17,
  2676. -34,
  2677. new [] { "กขฃคฅฆงจฉชซฌญฎฏฐฑ", "ฒณดตถทธนบปผฝพฟภมย", "รฤลฦวศษสหฬอฮฯะัาำ" }
  2678. )]
  2679. [InlineData (
  2680. "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ",
  2681. 13,
  2682. -38,
  2683. new [] { "กขฃคฅฆงจฉชซฌญ", "ฎฏฐฑฒณดตถทธนบ", "ปผฝพฟภมยรฤลฦว", "ศษสหฬอฮฯะัาำ" }
  2684. )]
  2685. [InlineData (
  2686. "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ",
  2687. 1,
  2688. -50,
  2689. new []
  2690. {
  2691. "ก",
  2692. "ข",
  2693. "ฃ",
  2694. "ค",
  2695. "ฅ",
  2696. "ฆ",
  2697. "ง",
  2698. "จ",
  2699. "ฉ",
  2700. "ช",
  2701. "ซ",
  2702. "ฌ",
  2703. "ญ",
  2704. "ฎ",
  2705. "ฏ",
  2706. "ฐ",
  2707. "ฑ",
  2708. "ฒ",
  2709. "ณ",
  2710. "ด",
  2711. "ต",
  2712. "ถ",
  2713. "ท",
  2714. "ธ",
  2715. "น",
  2716. "บ",
  2717. "ป",
  2718. "ผ",
  2719. "ฝ",
  2720. "พ",
  2721. "ฟ",
  2722. "ภ",
  2723. "ม",
  2724. "ย",
  2725. "ร",
  2726. "ฤ",
  2727. "ล",
  2728. "ฦ",
  2729. "ว",
  2730. "ศ",
  2731. "ษ",
  2732. "ส",
  2733. "ห",
  2734. "ฬ",
  2735. "อ",
  2736. "ฮ",
  2737. "ฯ",
  2738. "ะั",
  2739. "า",
  2740. "ำ"
  2741. }
  2742. )]
  2743. public void WordWrap_Unicode_SingleWordLine (
  2744. string text,
  2745. int maxWidth,
  2746. int widthOffset,
  2747. IEnumerable<string> resultLines
  2748. )
  2749. {
  2750. List<string> wrappedLines;
  2751. IEnumerable<Rune> zeroWidth = text.EnumerateRunes ().Where (r => r.GetColumns () == 0);
  2752. Assert.Single (zeroWidth);
  2753. Assert.Equal ('ั', zeroWidth.ElementAt (0).Value);
  2754. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2755. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2756. wrappedLines = TextFormatter.WordWrapText (text, maxWidth);
  2757. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2758. Assert.True (
  2759. expectedClippedWidth
  2760. >= (wrappedLines.Count > 0
  2761. ? wrappedLines.Max (
  2762. l => l.GetRuneCount ()
  2763. + zeroWidth.Count ()
  2764. - 1
  2765. + widthOffset
  2766. )
  2767. : 0)
  2768. );
  2769. Assert.True (
  2770. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2771. );
  2772. Assert.Equal (resultLines, wrappedLines);
  2773. }
  2774. /// <summary>WordWrap strips CRLF</summary>
  2775. [Theory]
  2776. [InlineData (
  2777. "A sentence has words.\nA paragraph has lines.",
  2778. 44,
  2779. 0,
  2780. new [] { "A sentence has words.A paragraph has lines." }
  2781. )]
  2782. [InlineData (
  2783. "A sentence has words.\nA paragraph has lines.",
  2784. 43,
  2785. -1,
  2786. new [] { "A sentence has words.A paragraph has lines." }
  2787. )]
  2788. [InlineData (
  2789. "A sentence has words.\nA paragraph has lines.",
  2790. 38,
  2791. -6,
  2792. new [] { "A sentence has words.A paragraph has", "lines." }
  2793. )]
  2794. [InlineData (
  2795. "A sentence has words.\nA paragraph has lines.",
  2796. 34,
  2797. -10,
  2798. new [] { "A sentence has words.A paragraph", "has lines." }
  2799. )]
  2800. [InlineData (
  2801. "A sentence has words.\nA paragraph has lines.",
  2802. 27,
  2803. -17,
  2804. new [] { "A sentence has words.A", "paragraph has lines." }
  2805. )]
  2806. // Unicode
  2807. [InlineData (
  2808. "A Unicode sentence (пÑивеÑ) has words.\nA Unicode Пункт has Линии.",
  2809. 69,
  2810. 0,
  2811. new [] { "A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has Линии." }
  2812. )]
  2813. [InlineData (
  2814. "A Unicode sentence (пÑивеÑ) has words.\nA Unicode Пункт has Линии.",
  2815. 68,
  2816. -1,
  2817. new [] { "A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has Линии." }
  2818. )]
  2819. [InlineData (
  2820. "A Unicode sentence (пÑивеÑ) has words.\nA Unicode Пункт has Линии.",
  2821. 63,
  2822. -6,
  2823. new [] { "A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has", "Линии." }
  2824. )]
  2825. [InlineData (
  2826. "A Unicode sentence (пÑивеÑ) has words.\nA Unicode Пункт has Линии.",
  2827. 59,
  2828. -10,
  2829. new [] { "A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт", "has Линии." }
  2830. )]
  2831. [InlineData (
  2832. "A Unicode sentence (пÑивеÑ) has words.\nA Unicode Пункт has Линии.",
  2833. 52,
  2834. -17,
  2835. new [] { "A Unicode sentence (пÑивеÑ) has words.A Unicode", "Пункт has Линии." }
  2836. )]
  2837. public void WordWrap_WithNewLines (string text, int maxWidth, int widthOffset, IEnumerable<string> resultLines)
  2838. {
  2839. List<string> wrappedLines;
  2840. Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);
  2841. int expectedClippedWidth = Math.Min (text.GetRuneCount (), maxWidth);
  2842. wrappedLines = TextFormatter.WordWrapText (text, maxWidth);
  2843. Assert.Equal (wrappedLines.Count, resultLines.Count ());
  2844. Assert.True (
  2845. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetRuneCount ()) : 0)
  2846. );
  2847. Assert.True (
  2848. expectedClippedWidth >= (wrappedLines.Count > 0 ? wrappedLines.Max (l => l.GetColumns ()) : 0)
  2849. );
  2850. Assert.Equal (resultLines, wrappedLines);
  2851. }
  2852. [SetupFakeDriver]
  2853. [Theory]
  2854. [InlineData ("A", 0, false, "")]
  2855. [InlineData ("A", 1, false, "A")]
  2856. [InlineData ("A", 2, false, "A")]
  2857. [InlineData ("AB", 1, false, "A")]
  2858. [InlineData ("AB", 2, false, "AB")]
  2859. [InlineData ("ABC", 3, false, "ABC")]
  2860. [InlineData ("ABC", 4, false, "ABC")]
  2861. [InlineData ("ABC", 6, false, "ABC")]
  2862. [InlineData ("A", 0, true, "")]
  2863. [InlineData ("A", 1, true, "A")]
  2864. [InlineData ("A", 2, true, "A")]
  2865. [InlineData ("AB", 1, true, "A")]
  2866. [InlineData ("AB", 2, true, "AB")]
  2867. [InlineData ("ABC", 3, true, "ABC")]
  2868. [InlineData ("ABC", 4, true, "ABC")]
  2869. [InlineData ("ABC", 6, true, "ABC")]
  2870. public void Draw_Horizontal_Left (string text, int width, bool autoSize, string expectedText)
  2871. {
  2872. TextFormatter tf = new ()
  2873. {
  2874. Text = text,
  2875. Alignment = Alignment.Start,
  2876. AutoSize = autoSize,
  2877. };
  2878. if (!autoSize)
  2879. {
  2880. tf.Size = new Size (width, 1);
  2881. }
  2882. tf.Draw (new Rectangle (0, 0, width, 1), Attribute.Default, Attribute.Default);
  2883. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  2884. }
  2885. [SetupFakeDriver]
  2886. [Theory]
  2887. [InlineData ("A", 0, false, "")]
  2888. [InlineData ("A", 1, false, "A")]
  2889. [InlineData ("A", 2, false, " A")]
  2890. [InlineData ("AB", 1, false, "B")]
  2891. [InlineData ("AB", 2, false, "AB")]
  2892. [InlineData ("ABC", 3, false, "ABC")]
  2893. [InlineData ("ABC", 4, false, " ABC")]
  2894. [InlineData ("ABC", 6, false, " ABC")]
  2895. [InlineData ("A", 0, true, "")]
  2896. [InlineData ("A", 1, true, "A")]
  2897. [InlineData ("A", 2, true, " A")]
  2898. [InlineData ("AB", 1, true, "B")]
  2899. [InlineData ("AB", 2, true, "AB")]
  2900. [InlineData ("ABC", 3, true, "ABC")]
  2901. [InlineData ("ABC", 4, true, " ABC")]
  2902. [InlineData ("ABC", 6, true, " ABC")]
  2903. public void Draw_Horizontal_Right (string text, int width, bool autoSize, string expectedText)
  2904. {
  2905. TextFormatter tf = new ()
  2906. {
  2907. Text = text,
  2908. Alignment = Alignment.End,
  2909. AutoSize = autoSize,
  2910. };
  2911. if (!autoSize)
  2912. {
  2913. tf.Size = new Size (width, 1);
  2914. }
  2915. tf.Draw (new Rectangle (Point.Empty, new (width, 1)), Attribute.Default, Attribute.Default);
  2916. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  2917. }
  2918. [SetupFakeDriver]
  2919. [Theory]
  2920. [InlineData ("A", 0, false, "")]
  2921. [InlineData ("A", 1, false, "A")]
  2922. [InlineData ("A", 2, false, "A")]
  2923. [InlineData ("A", 3, false, " A")]
  2924. [InlineData ("AB", 1, false, "A")]
  2925. [InlineData ("AB", 2, false, "AB")]
  2926. [InlineData ("ABC", 3, false, "ABC")]
  2927. [InlineData ("ABC", 4, false, "ABC")]
  2928. [InlineData ("ABC", 5, false, " ABC")]
  2929. [InlineData ("ABC", 6, false, " ABC")]
  2930. [InlineData ("ABC", 9, false, " ABC")]
  2931. [InlineData ("A", 0, true, "")]
  2932. [InlineData ("A", 1, true, "A")]
  2933. [InlineData ("A", 2, true, "A")]
  2934. [InlineData ("A", 3, true, " A")]
  2935. [InlineData ("AB", 1, true, "A")]
  2936. [InlineData ("AB", 2, true, "AB")]
  2937. [InlineData ("ABC", 3, true, "ABC")]
  2938. [InlineData ("ABC", 4, true, "ABC")]
  2939. [InlineData ("ABC", 5, true, " ABC")]
  2940. [InlineData ("ABC", 6, true, " ABC")]
  2941. [InlineData ("ABC", 9, true, " ABC")]
  2942. public void Draw_Horizontal_Centered (string text, int width, bool autoSize, string expectedText)
  2943. {
  2944. TextFormatter tf = new ()
  2945. {
  2946. Text = text,
  2947. Alignment = Alignment.Center,
  2948. AutoSize = autoSize,
  2949. };
  2950. if (!autoSize)
  2951. {
  2952. tf.Size = new Size (width, 1);
  2953. }
  2954. tf.Draw (new Rectangle (0, 0, width, 1), Attribute.Default, Attribute.Default);
  2955. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  2956. }
  2957. [SetupFakeDriver]
  2958. [Theory]
  2959. [InlineData ("A", 0, false, "")]
  2960. [InlineData ("A", 1, false, "A")]
  2961. [InlineData ("A", 2, false, "A")]
  2962. [InlineData ("A B", 3, false, "A B")]
  2963. [InlineData ("A B", 1, false, "A")]
  2964. [InlineData ("A B", 2, false, "A")]
  2965. [InlineData ("A B", 4, false, "A B")]
  2966. [InlineData ("A B", 5, false, "A B")]
  2967. [InlineData ("A B", 6, false, "A B")]
  2968. [InlineData ("A B", 10, false, "A B")]
  2969. [InlineData ("ABC ABC", 10, false, "ABC ABC")]
  2970. [InlineData ("A", 0, true, "")]
  2971. [InlineData ("A", 1, true, "A")]
  2972. [InlineData ("A", 2, true, "A")]
  2973. [InlineData ("A B", 1, true, "A")]
  2974. [InlineData ("A B", 2, true, "A")]
  2975. [InlineData ("A B", 3, true, "A B")]
  2976. [InlineData ("A B", 4, true, "A B")]
  2977. [InlineData ("A B", 5, true, "A B")]
  2978. [InlineData ("A B", 6, true, "A B")]
  2979. [InlineData ("A B", 10, true, "A B")]
  2980. [InlineData ("ABC ABC", 10, true, "ABC ABC")]
  2981. public void Draw_Horizontal_Justified (string text, int width, bool autoSize, string expectedText)
  2982. {
  2983. TextFormatter tf = new ()
  2984. {
  2985. Text = text,
  2986. Alignment = Alignment.Fill,
  2987. AutoSize = autoSize,
  2988. };
  2989. if (!autoSize)
  2990. {
  2991. tf.Size = new Size (width, 1);
  2992. }
  2993. tf.Draw (new Rectangle (0, 0, width, 1), Attribute.Default, Attribute.Default);
  2994. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  2995. }
  2996. [SetupFakeDriver]
  2997. [Theory]
  2998. [InlineData ("A", 5, 5, false, "A")]
  2999. [InlineData ("AB12", 5, 5, false, @"
  3000. A
  3001. B
  3002. 1
  3003. 2")]
  3004. [InlineData ("AB\n12", 5, 5, false, @"
  3005. A1
  3006. B2")]
  3007. [InlineData ("", 5, 1, false, "")]
  3008. [InlineData ("Hello Worlds", 1, 12, true, @"
  3009. H
  3010. e
  3011. l
  3012. l
  3013. o
  3014. W
  3015. o
  3016. r
  3017. l
  3018. d
  3019. s")]
  3020. [InlineData ("Hello Worlds", 1, 12, false, @"
  3021. H
  3022. e
  3023. l
  3024. l
  3025. o
  3026. W
  3027. o
  3028. r
  3029. l
  3030. d
  3031. s")]
  3032. [InlineData ("Hello Worlds", 12, 1, false, @"HelloWorlds")]
  3033. public void Draw_Vertical_TopBottom_LeftRight (string text, int width, int height, bool autoSize, string expectedText)
  3034. {
  3035. TextFormatter tf = new ()
  3036. {
  3037. Text = text,
  3038. AutoSize = autoSize,
  3039. Direction = TextDirection.TopBottom_LeftRight,
  3040. };
  3041. if (!autoSize)
  3042. {
  3043. tf.Size = new Size (width, height);
  3044. }
  3045. tf.Draw (new Rectangle (0, 0, 20, 20), Attribute.Default, Attribute.Default);
  3046. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  3047. }
  3048. [SetupFakeDriver]
  3049. [Theory]
  3050. [InlineData ("Hello World", 15, 1, "Hello World")]
  3051. [InlineData ("Well Done\nNice Work", 15, 2, @"
  3052. Well Done
  3053. Nice Work")]
  3054. [InlineData ("你好 世界", 15, 1, "你好 世界")]
  3055. [InlineData ("做 得好\n幹 得好", 15, 2, @"
  3056. 做 得好
  3057. 幹 得好")]
  3058. public void Justify_Horizontal (string text, int width, int height, string expectedText)
  3059. {
  3060. TextFormatter tf = new ()
  3061. {
  3062. Text = text,
  3063. Alignment = Alignment.Fill,
  3064. Size = new Size (width, height),
  3065. MultiLine = true
  3066. };
  3067. tf.Draw (new Rectangle (0, 0, width, height), Attribute.Default, Attribute.Default);
  3068. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  3069. }
  3070. [SetupFakeDriver]
  3071. [Theory]
  3072. [InlineData ("Hello World", 1, 15, "H\ne\nl\nl\no\n \n \n \n \n \nW\no\nr\nl\nd")]
  3073. [InlineData ("Well Done\nNice Work", 2, 15, @"
  3074. WN
  3075. ei
  3076. lc
  3077. le
  3078. DW
  3079. oo
  3080. nr
  3081. ek")]
  3082. [InlineData ("你好 世界", 2, 15, "你\n好\n \n \n \n \n \n \n \n \n \n \n \n世\n界")]
  3083. [InlineData ("做 得好\n幹 得好", 4, 15, @"
  3084. 做幹
  3085. 得得
  3086. 好好")]
  3087. public void Justify_Vertical (string text, int width, int height, string expectedText)
  3088. {
  3089. TextFormatter tf = new ()
  3090. {
  3091. Text = text,
  3092. Direction = TextDirection.TopBottom_LeftRight,
  3093. VerticalAlignment = Alignment.Fill,
  3094. Size = new Size (width, height),
  3095. MultiLine = true
  3096. };
  3097. tf.Draw (new Rectangle (0, 0, width, height), Attribute.Default, Attribute.Default);
  3098. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  3099. }
  3100. [SetupFakeDriver]
  3101. [Theory]
  3102. [InlineData ("A", 0, 1, false, "", 0)]
  3103. [InlineData ("A", 1, 1, false, "A", 0)]
  3104. [InlineData ("A", 2, 2, false, " A", 1)]
  3105. [InlineData ("AB", 1, 1, false, "B", 0)]
  3106. [InlineData ("AB", 2, 2, false, " A\n B", 0)]
  3107. [InlineData ("ABC", 3, 2, false, " B\n C", 0)]
  3108. [InlineData ("ABC", 4, 2, false, " B\n C", 0)]
  3109. [InlineData ("ABC", 6, 2, false, " B\n C", 0)]
  3110. [InlineData ("こんにちは", 0, 1, false, "", 0)]
  3111. [InlineData ("こんにちは", 1, 0, false, "", 0)]
  3112. [InlineData ("こんにちは", 1, 1, false, "", 0)]
  3113. [InlineData ("こんにちは", 2, 1, false, "は", 0)]
  3114. [InlineData ("こんにちは", 2, 2, false, "ち\nは", 0)]
  3115. [InlineData ("こんにちは", 2, 3, false, "に\nち\nは", 0)]
  3116. [InlineData ("こんにちは", 2, 4, false, "ん\nに\nち\nは", 0)]
  3117. [InlineData ("こんにちは", 2, 5, false, "こ\nん\nに\nち\nは", 0)]
  3118. [InlineData ("こんにちは", 2, 6, false, "こ\nん\nに\nち\nは", 1)]
  3119. [InlineData ("ABCD\nこんにちは", 4, 7, false, " こ\n Aん\n Bに\n Cち\n Dは", 2)]
  3120. [InlineData ("こんにちは\nABCD", 3, 7, false, "こ \nんA\nにB\nちC\nはD", 2)]
  3121. [InlineData ("A", 0, 1, true, "", 0)]
  3122. [InlineData ("A", 1, 1, true, "A", 0)]
  3123. [InlineData ("A", 2, 2, true, " A", 1)]
  3124. [InlineData ("AB", 1, 1, true, "B", 0)]
  3125. [InlineData ("AB", 2, 2, true, " A\n B", 0)]
  3126. [InlineData ("ABC", 3, 2, true, " B\n C", 0)]
  3127. [InlineData ("ABC", 4, 2, true, " B\n C", 0)]
  3128. [InlineData ("ABC", 6, 2, true, " B\n C", 0)]
  3129. [InlineData ("こんにちは", 0, 1, true, "", 0)]
  3130. [InlineData ("こんにちは", 1, 0, true, "", 0)]
  3131. [InlineData ("こんにちは", 1, 1, true, "", 0)]
  3132. [InlineData ("こんにちは", 2, 1, true, "は", 0)]
  3133. [InlineData ("こんにちは", 2, 2, true, "ち\nは", 0)]
  3134. [InlineData ("こんにちは", 2, 3, true, "に\nち\nは", 0)]
  3135. [InlineData ("こんにちは", 2, 4, true, "ん\nに\nち\nは", 0)]
  3136. [InlineData ("こんにちは", 2, 5, true, "こ\nん\nに\nち\nは", 0)]
  3137. [InlineData ("こんにちは", 2, 6, true, "こ\nん\nに\nち\nは", 1)]
  3138. [InlineData ("ABCD\nこんにちは", 4, 7, true, " こ\n Aん\n Bに\n Cち\n Dは", 2)]
  3139. [InlineData ("こんにちは\nABCD", 3, 7, true, "こ \nんA\nにB\nちC\nはD", 2)]
  3140. public void Draw_Vertical_Bottom_Horizontal_Right (string text, int width, int height, bool autoSize, string expectedText, int expectedY)
  3141. {
  3142. TextFormatter tf = new ()
  3143. {
  3144. Text = text,
  3145. Alignment = Alignment.End,
  3146. Direction = TextDirection.TopBottom_LeftRight,
  3147. VerticalAlignment = Alignment.End,
  3148. AutoSize = autoSize,
  3149. };
  3150. if (!autoSize)
  3151. {
  3152. tf.Size = new Size (width, height);
  3153. }
  3154. tf.Draw (new Rectangle (Point.Empty, new (width, height)), Attribute.Default, Attribute.Default);
  3155. Rectangle rect = TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  3156. Assert.Equal (expectedY, rect.Y);
  3157. }
  3158. [SetupFakeDriver]
  3159. [Theory]
  3160. [InlineData ("A", 5, false, "A")]
  3161. [InlineData ("AB12", 5, false, @"
  3162. A
  3163. B
  3164. 1
  3165. 2")]
  3166. [InlineData ("AB\n12", 5, false, @"
  3167. A1
  3168. B2")]
  3169. [InlineData ("", 1, false, "")]
  3170. [InlineData ("AB1 2", 2, false, @"
  3171. A12
  3172. B ")]
  3173. [InlineData ("こんにちは", 1, false, @"
  3174. こん")]
  3175. [InlineData ("こんにちは", 2, false, @"
  3176. こに
  3177. んち")]
  3178. [InlineData ("こんにちは", 5, false, @"
  3179. は")]
  3180. [InlineData ("A", 5, true, "A")]
  3181. [InlineData ("AB12", 5, true, @"
  3182. A
  3183. B
  3184. 1
  3185. 2")]
  3186. [InlineData ("AB\n12", 5, true, @"
  3187. A1
  3188. B2")]
  3189. [InlineData ("", 1, true, "")]
  3190. [InlineData ("AB1 2", 2, true, @"
  3191. A
  3192. B")]
  3193. [InlineData ("こんにちは", 1, true, @"
  3194. こ")]
  3195. [InlineData ("こんにちは", 2, true, @"
  3196. ん")]
  3197. [InlineData ("こんにちは", 5, true, @"
  3198. は")]
  3199. public void Draw_Vertical_TopBottom_LeftRight_Top (string text, int height, bool autoSize, string expectedText)
  3200. {
  3201. TextFormatter tf = new ()
  3202. {
  3203. Text = text,
  3204. AutoSize = autoSize,
  3205. Direction = TextDirection.TopBottom_LeftRight,
  3206. };
  3207. if (!autoSize)
  3208. {
  3209. tf.Size = new Size (5, height);
  3210. }
  3211. tf.Draw (new Rectangle (0, 0, 5, height), Attribute.Default, Attribute.Default);
  3212. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  3213. }
  3214. [SetupFakeDriver]
  3215. [Theory]
  3216. // The expectedY param is to probe that the expectedText param start at that Y coordinate
  3217. [InlineData ("A", 0, false, "", 0)]
  3218. [InlineData ("A", 1, false, "A", 0)]
  3219. [InlineData ("A", 2, false, "A", 0)]
  3220. [InlineData ("A", 3, false, "A", 1)]
  3221. [InlineData ("AB", 1, false, "A", 0)]
  3222. [InlineData ("AB", 2, false, "A\nB", 0)]
  3223. [InlineData ("ABC", 2, false, "A\nB", 0)]
  3224. [InlineData ("ABC", 3, false, "A\nB\nC", 0)]
  3225. [InlineData ("ABC", 4, false, "A\nB\nC", 0)]
  3226. [InlineData ("ABC", 5, false, "A\nB\nC", 1)]
  3227. [InlineData ("ABC", 6, false, "A\nB\nC", 1)]
  3228. [InlineData ("ABC", 9, false, "A\nB\nC", 3)]
  3229. [InlineData ("ABCD", 2, false, "B\nC", 0)]
  3230. [InlineData ("こんにちは", 0, false, "", 0)]
  3231. [InlineData ("こんにちは", 1, false, "に", 0)]
  3232. [InlineData ("こんにちは", 2, false, "ん\nに", 0)]
  3233. [InlineData ("こんにちは", 3, false, "ん\nに\nち", 0)]
  3234. [InlineData ("こんにちは", 4, false, "こ\nん\nに\nち", 0)]
  3235. [InlineData ("こんにちは", 5, false, "こ\nん\nに\nち\nは", 0)]
  3236. [InlineData ("こんにちは", 6, false, "こ\nん\nに\nち\nは", 0)]
  3237. [InlineData ("ABCD\nこんにちは", 7, false, "Aこ\nBん\nCに\nDち\n は", 1)]
  3238. [InlineData ("こんにちは\nABCD", 7, false, "こA\nんB\nにC\nちD\nは ", 1)]
  3239. [InlineData ("A", 0, true, "", 0)]
  3240. [InlineData ("A", 1, true, "A", 0)]
  3241. [InlineData ("A", 2, true, "A", 0)]
  3242. [InlineData ("A", 3, true, "A", 1)]
  3243. [InlineData ("AB", 1, true, "A", 0)]
  3244. [InlineData ("AB", 2, true, "A\nB", 0)]
  3245. [InlineData ("ABC", 2, true, "A\nB", 0)]
  3246. [InlineData ("ABC", 3, true, "A\nB\nC", 0)]
  3247. [InlineData ("ABC", 4, true, "A\nB\nC", 0)]
  3248. [InlineData ("ABC", 5, true, "A\nB\nC", 1)]
  3249. [InlineData ("ABC", 6, true, "A\nB\nC", 1)]
  3250. [InlineData ("ABC", 9, true, "A\nB\nC", 3)]
  3251. [InlineData ("ABCD", 2, true, "B\nC", 0)]
  3252. [InlineData ("こんにちは", 0, true, "", 0)]
  3253. [InlineData ("こんにちは", 1, true, "に", 0)]
  3254. [InlineData ("こんにちは", 2, true, "ん\nに", 0)]
  3255. [InlineData ("こんにちは", 3, true, "ん\nに\nち", 0)]
  3256. [InlineData ("こんにちは", 4, true, "こ\nん\nに\nち", 0)]
  3257. [InlineData ("こんにちは", 5, true, "こ\nん\nに\nち\nは", 0)]
  3258. [InlineData ("こんにちは", 6, true, "こ\nん\nに\nち\nは", 0)]
  3259. [InlineData ("こんにちは", 7, true, "こ\nん\nに\nち\nは", 1)]
  3260. [InlineData ("ABCD\nこんにちは", 7, true, "Aこ\nBん\nCに\nDち\n は", 1)]
  3261. [InlineData ("こんにちは\nABCD", 7, true, "こA\nんB\nにC\nちD\nは ", 1)]
  3262. public void Draw_Vertical_TopBottom_LeftRight_Middle (string text, int height, bool autoSize, string expectedText, int expectedY)
  3263. {
  3264. TextFormatter tf = new ()
  3265. {
  3266. Text = text,
  3267. Direction = TextDirection.TopBottom_LeftRight,
  3268. VerticalAlignment = Alignment.Center,
  3269. AutoSize = autoSize,
  3270. };
  3271. if (!autoSize)
  3272. {
  3273. int width = text.ToRunes ().Max (r => r.GetColumns ());
  3274. if (text.Contains ("\n"))
  3275. {
  3276. width++;
  3277. }
  3278. tf.Size = new Size (width, height);
  3279. }
  3280. tf.Draw (new Rectangle (0, 0, 5, height), Attribute.Default, Attribute.Default);
  3281. Rectangle rect = TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  3282. Assert.Equal (expectedY, rect.Y);
  3283. }
  3284. [Theory]
  3285. [InlineData ("1234", 4)]
  3286. [InlineData ("_1234", 4)]
  3287. public void AutoSize_HotKey_Size_Correct (string text, int expected)
  3288. {
  3289. // Horizontal
  3290. TextFormatter tf = new ()
  3291. {
  3292. AutoSize = true,
  3293. HotKeySpecifier = (Rune)'_',
  3294. Text = text,
  3295. };
  3296. Assert.Equal (new (expected, 1), tf.Size);
  3297. // Vertical
  3298. tf = new ()
  3299. {
  3300. HotKeySpecifier = (Rune)'_',
  3301. Direction = TextDirection.TopBottom_LeftRight,
  3302. Text = text,
  3303. AutoSize = true,
  3304. };
  3305. Assert.Equal (new (1, expected), tf.Size);
  3306. }
  3307. [SetupFakeDriver]
  3308. [Theory]
  3309. [InlineData ("A", 1, 0, false, "")]
  3310. [InlineData ("A", 0, 1, false, "")]
  3311. [InlineData ("AB1 2", 2, 1, false, "2")]
  3312. [InlineData ("AB12", 5, 1, false, "21BA")]
  3313. [InlineData ("AB\n12", 5, 2, false, "BA\n21")]
  3314. [InlineData ("ABC 123 456", 7, 2, false, "654 321\nCBA ")]
  3315. [InlineData ("こんにちは", 1, 1, false, "")]
  3316. [InlineData ("こんにちは", 2, 1, false, "は")]
  3317. [InlineData ("こんにちは", 5, 1, false, "はち")]
  3318. [InlineData ("こんにちは", 10, 1, false, "はちにんこ")]
  3319. [InlineData ("こんにちは\nAB\n12", 10, 3, false, "はちにんこ\nBA \n21 ")]
  3320. [InlineData ("A", 1, 0, true, "")]
  3321. [InlineData ("A", 0, 1, true, "")]
  3322. [InlineData ("AB1 2", 2, 1, true, "2")]
  3323. [InlineData ("AB12", 5, 1, true, "21BA")]
  3324. [InlineData ("AB\n12", 5, 2, true, "BA\n21")]
  3325. [InlineData ("ABC 123 456", 7, 2, true, "654 321")]
  3326. [InlineData ("こんにちは", 1, 1, true, "")]
  3327. [InlineData ("こんにちは", 2, 1, true, "は")]
  3328. [InlineData ("こんにちは", 5, 1, true, "はち")]
  3329. [InlineData ("こんにちは", 10, 1, true, "はちにんこ")]
  3330. [InlineData ("こんにちは\nAB\n12", 10, 3, true, "はちにんこ\nBA \n21 ")]
  3331. public void Draw_Horizontal_RightLeft_TopBottom (string text, int width, int height, bool autoSize, string expectedText)
  3332. {
  3333. TextFormatter tf = new ()
  3334. {
  3335. Text = text,
  3336. Direction = TextDirection.RightLeft_TopBottom,
  3337. AutoSize = autoSize,
  3338. };
  3339. if (!autoSize)
  3340. {
  3341. tf.Size = new Size (width, height);
  3342. }
  3343. tf.Draw (new Rectangle (0, 0, width, height), Attribute.Default, Attribute.Default);
  3344. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  3345. }
  3346. [SetupFakeDriver]
  3347. [Theory]
  3348. [InlineData ("A", 1, 0, false, "")]
  3349. [InlineData ("A", 0, 1, false, "")]
  3350. [InlineData ("AB1 2", 2, 1, false, "2")]
  3351. [InlineData ("AB12", 5, 1, false, "21BA")]
  3352. [InlineData ("AB\n12", 5, 2, false, "21\nBA")]
  3353. [InlineData ("ABC 123 456", 7, 2, false, "CBA \n654 321")]
  3354. [InlineData ("こんにちは", 1, 1, false, "")]
  3355. [InlineData ("こんにちは", 2, 1, false, "は")]
  3356. [InlineData ("こんにちは", 5, 1, false, "はち")]
  3357. [InlineData ("こんにちは", 10, 1, false, "はちにんこ")]
  3358. [InlineData ("こんにちは\nAB\n12", 10, 3, false, "21 \nBA \nはちにんこ")]
  3359. [InlineData ("A", 1, 0, true, "")]
  3360. [InlineData ("A", 0, 1, true, "")]
  3361. [InlineData ("AB1 2", 2, 1, true, "2")]
  3362. [InlineData ("AB12", 5, 1, true, "21BA")]
  3363. [InlineData ("AB\n12", 5, 2, true, "21\nBA")]
  3364. [InlineData ("ABC 123 456", 7, 2, true, "654 321")]
  3365. [InlineData ("こんにちは", 1, 1, true, "")]
  3366. [InlineData ("こんにちは", 2, 1, true, "は")]
  3367. [InlineData ("こんにちは", 5, 1, true, "はち")]
  3368. [InlineData ("こんにちは", 10, 1, true, "はちにんこ")]
  3369. [InlineData ("こんにちは\nAB\n12", 10, 3, true, "21 \nBA \nはちにんこ")]
  3370. public void Draw_Horizontal_RightLeft_BottomTop (string text, int width, int height, bool autoSize, string expectedText)
  3371. {
  3372. TextFormatter tf = new ()
  3373. {
  3374. Text = text,
  3375. Direction = TextDirection.RightLeft_BottomTop,
  3376. AutoSize = autoSize,
  3377. };
  3378. if (!autoSize)
  3379. {
  3380. tf.Size = new Size (width, height);
  3381. }
  3382. tf.Draw (new Rectangle (0, 0, width, height), Attribute.Default, Attribute.Default);
  3383. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  3384. }
  3385. [SetupFakeDriver]
  3386. [Theory]
  3387. [InlineData ("A", 1, 0, false, "")]
  3388. [InlineData ("A", 0, 1, false, "")]
  3389. [InlineData ("AB1 2", 1, 2, false, "2")]
  3390. [InlineData ("AB12", 1, 5, false, "2\n1\nB\nA")]
  3391. [InlineData ("AB\n12", 2, 5, false, "B2\nA1")]
  3392. [InlineData ("ABC 123 456", 2, 7, false, "6C\n5B\n4A\n \n3 \n2 \n1 ")]
  3393. [InlineData ("こんにちは", 1, 1, false, "")]
  3394. [InlineData ("こんにちは", 2, 1, false, "は")]
  3395. [InlineData ("こんにちは", 2, 5, false, "は\nち\nに\nん\nこ")]
  3396. [InlineData ("こんにちは", 2, 10, false, "は\nち\nに\nん\nこ")]
  3397. [InlineData ("こんにちは\nAB\n12", 4, 10, false, "はB2\nちA1\nに \nん \nこ ")]
  3398. [InlineData ("A", 1, 0, true, "")]
  3399. [InlineData ("A", 0, 1, true, "")]
  3400. [InlineData ("AB1 2", 1, 2, true, "2")]
  3401. [InlineData ("AB12", 1, 5, true, "2\n1\nB\nA")]
  3402. [InlineData ("AB\n12", 2, 5, true, "B2\nA1")]
  3403. [InlineData ("ABC 123 456", 2, 7, true, "6\n5\n4\n \n3\n2\n1")]
  3404. [InlineData ("こんにちは", 1, 1, true, "")]
  3405. [InlineData ("こんにちは", 2, 1, true, "は")]
  3406. [InlineData ("こんにちは", 2, 5, true, "は\nち\nに\nん\nこ")]
  3407. [InlineData ("こんにちは", 2, 10, true, "は\nち\nに\nん\nこ")]
  3408. [InlineData ("こんにちは\nAB\n12", 4, 10, true, "はB2\nちA1\nに \nん \nこ ")]
  3409. public void Draw_Vertical_BottomTop_LeftRight (string text, int width, int height, bool autoSize, string expectedText)
  3410. {
  3411. TextFormatter tf = new ()
  3412. {
  3413. Text = text,
  3414. Direction = TextDirection.BottomTop_LeftRight,
  3415. AutoSize = autoSize,
  3416. };
  3417. if (!autoSize)
  3418. {
  3419. tf.Size = new Size (width, height);
  3420. }
  3421. tf.Draw (new Rectangle (0, 0, width, height), Attribute.Default, Attribute.Default);
  3422. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  3423. }
  3424. [SetupFakeDriver]
  3425. [Theory]
  3426. [InlineData ("A", 1, 0, false, "")]
  3427. [InlineData ("A", 0, 1, false, "")]
  3428. [InlineData ("AB1 2", 1, 2, false, "2")]
  3429. [InlineData ("AB12", 1, 5, false, "2\n1\nB\nA")]
  3430. [InlineData ("AB\n12", 2, 5, false, "2B\n1A")]
  3431. [InlineData ("ABC 123 456", 2, 7, false, "C6\nB5\nA4\n \n 3\n 2\n 1")]
  3432. [InlineData ("こんにちは", 1, 1, false, "")]
  3433. [InlineData ("こんにちは", 2, 1, false, "は")]
  3434. [InlineData ("こんにちは", 2, 5, false, "は\nち\nに\nん\nこ")]
  3435. [InlineData ("こんにちは", 2, 10, false, "は\nち\nに\nん\nこ")]
  3436. [InlineData ("こんにちは\nAB\n12", 4, 10, false, "2Bは\n1Aち\n に\n ん\n こ")]
  3437. [InlineData ("A", 1, 0, true, "")]
  3438. [InlineData ("A", 0, 1, true, "")]
  3439. [InlineData ("AB1 2", 1, 2, true, "2")]
  3440. [InlineData ("AB12", 1, 5, true, "2\n1\nB\nA")]
  3441. [InlineData ("AB\n12", 2, 5, true, "2B\n1A")]
  3442. [InlineData ("ABC 123 456", 2, 7, true, "6\n5\n4\n \n3\n2\n1")]
  3443. [InlineData ("こんにちは", 1, 1, true, "")]
  3444. [InlineData ("こんにちは", 2, 1, true, "は")]
  3445. [InlineData ("こんにちは", 2, 5, true, "は\nち\nに\nん\nこ")]
  3446. [InlineData ("こんにちは", 2, 10, true, "は\nち\nに\nん\nこ")]
  3447. [InlineData ("こんにちは\nAB\n12", 4, 10, true, "2Bは\n1Aち\n に\n ん\n こ")]
  3448. public void Draw_Vertical_BottomTop_RightLeft (string text, int width, int height, bool autoSize, string expectedText)
  3449. {
  3450. TextFormatter tf = new ()
  3451. {
  3452. Text = text,
  3453. Direction = TextDirection.BottomTop_RightLeft,
  3454. AutoSize = autoSize,
  3455. };
  3456. if (!autoSize)
  3457. {
  3458. tf.Size = new Size (width, height);
  3459. }
  3460. tf.Draw (new Rectangle (0, 0, width, height), Attribute.Default, Attribute.Default);
  3461. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  3462. }
  3463. // Draw tests - Note that these depend on View
  3464. [Fact]
  3465. [TestRespondersDisposed]
  3466. public void Draw_Vertical_Throws_IndexOutOfRangeException_With_Negative_Bounds ()
  3467. {
  3468. Application.Init (new FakeDriver ());
  3469. Toplevel top = new ();
  3470. var view = new View { Y = -2, Height = 10, TextDirection = TextDirection.TopBottom_LeftRight, Text = "view" };
  3471. top.Add (view);
  3472. Application.Iteration += (s, a) =>
  3473. {
  3474. Assert.Equal (-2, view.Y);
  3475. Application.RequestStop ();
  3476. };
  3477. try
  3478. {
  3479. Application.Run (top);
  3480. }
  3481. catch (IndexOutOfRangeException ex)
  3482. {
  3483. // After the fix this exception will not be caught.
  3484. Assert.IsType<IndexOutOfRangeException> (ex);
  3485. }
  3486. top.Dispose ();
  3487. // Shutdown must be called to safely clean up Application if Init has been called
  3488. Application.Shutdown ();
  3489. }
  3490. [SetupFakeDriver]
  3491. [Theory]
  3492. // Horizontal with Alignment.Start
  3493. // LeftRight_TopBottom
  3494. [InlineData ("0 2 4", Alignment.Start, Alignment.Start, TextDirection.LeftRight_TopBottom, @"
  3495. 0 2 4**
  3496. *******
  3497. *******
  3498. *******
  3499. *******
  3500. *******
  3501. *******")]
  3502. [InlineData ("0 2 4", Alignment.End, Alignment.Start, TextDirection.LeftRight_TopBottom, @"
  3503. **0 2 4
  3504. *******
  3505. *******
  3506. *******
  3507. *******
  3508. *******
  3509. *******")]
  3510. [InlineData ("0 2 4", Alignment.Center, Alignment.Start, TextDirection.LeftRight_TopBottom, @"
  3511. *0 2 4*
  3512. *******
  3513. *******
  3514. *******
  3515. *******
  3516. *******
  3517. *******")]
  3518. [InlineData ("0 2 4", Alignment.Fill, Alignment.Start, TextDirection.LeftRight_TopBottom, @"
  3519. 0 2 4
  3520. *******
  3521. *******
  3522. *******
  3523. *******
  3524. *******
  3525. *******")]
  3526. [InlineData ("0 你 4", Alignment.Start, Alignment.Start, TextDirection.LeftRight_TopBottom, @"
  3527. 0 你 4*
  3528. *******
  3529. *******
  3530. *******
  3531. *******
  3532. *******
  3533. *******")]
  3534. [InlineData ("0 你 4", Alignment.End, Alignment.Start, TextDirection.LeftRight_TopBottom, @"
  3535. *0 你 4
  3536. *******
  3537. *******
  3538. *******
  3539. *******
  3540. *******
  3541. *******")]
  3542. [InlineData ("0 你 4", Alignment.Center, Alignment.Start, TextDirection.LeftRight_TopBottom, @"
  3543. 0 你 4*
  3544. *******
  3545. *******
  3546. *******
  3547. *******
  3548. *******
  3549. *******")]
  3550. [InlineData ("0 你 4", Alignment.Fill, Alignment.Start, TextDirection.LeftRight_TopBottom, @"
  3551. 0 你 4
  3552. *******
  3553. *******
  3554. *******
  3555. *******
  3556. *******
  3557. *******")]
  3558. // LeftRight_BottomTop
  3559. [InlineData ("0 2 4", Alignment.Start, Alignment.Start, TextDirection.LeftRight_BottomTop, @"
  3560. 0 2 4**
  3561. *******
  3562. *******
  3563. *******
  3564. *******
  3565. *******
  3566. *******")]
  3567. [InlineData ("0 2 4", Alignment.End, Alignment.Start, TextDirection.LeftRight_BottomTop, @"
  3568. **0 2 4
  3569. *******
  3570. *******
  3571. *******
  3572. *******
  3573. *******
  3574. *******")]
  3575. [InlineData ("0 2 4", Alignment.Center, Alignment.Start, TextDirection.LeftRight_BottomTop, @"
  3576. *0 2 4*
  3577. *******
  3578. *******
  3579. *******
  3580. *******
  3581. *******
  3582. *******")]
  3583. [InlineData ("0 2 4", Alignment.Fill, Alignment.Start, TextDirection.LeftRight_BottomTop, @"
  3584. 0 2 4
  3585. *******
  3586. *******
  3587. *******
  3588. *******
  3589. *******
  3590. *******")]
  3591. [InlineData ("0 你 4", Alignment.Start, Alignment.Start, TextDirection.LeftRight_BottomTop, @"
  3592. 0 你 4*
  3593. *******
  3594. *******
  3595. *******
  3596. *******
  3597. *******
  3598. *******")]
  3599. [InlineData ("0 你 4", Alignment.End, Alignment.Start, TextDirection.LeftRight_BottomTop, @"
  3600. *0 你 4
  3601. *******
  3602. *******
  3603. *******
  3604. *******
  3605. *******
  3606. *******")]
  3607. [InlineData ("0 你 4", Alignment.Center, Alignment.Start, TextDirection.LeftRight_BottomTop, @"
  3608. 0 你 4*
  3609. *******
  3610. *******
  3611. *******
  3612. *******
  3613. *******
  3614. *******")]
  3615. [InlineData ("0 你 4", Alignment.Fill, Alignment.Start, TextDirection.LeftRight_BottomTop, @"
  3616. 0 你 4
  3617. *******
  3618. *******
  3619. *******
  3620. *******
  3621. *******
  3622. *******")]
  3623. // RightLeft_TopBottom
  3624. [InlineData ("0 2 4", Alignment.Start, Alignment.Start, TextDirection.RightLeft_TopBottom, @"
  3625. 4 2 0**
  3626. *******
  3627. *******
  3628. *******
  3629. *******
  3630. *******
  3631. *******")]
  3632. [InlineData ("0 2 4", Alignment.End, Alignment.Start, TextDirection.RightLeft_TopBottom, @"
  3633. **4 2 0
  3634. *******
  3635. *******
  3636. *******
  3637. *******
  3638. *******
  3639. *******")]
  3640. [InlineData ("0 2 4", Alignment.Center, Alignment.Start, TextDirection.RightLeft_TopBottom, @"
  3641. *4 2 0*
  3642. *******
  3643. *******
  3644. *******
  3645. *******
  3646. *******
  3647. *******")]
  3648. [InlineData ("0 2 4", Alignment.Fill, Alignment.Start, TextDirection.RightLeft_TopBottom, @"
  3649. 4 2 0
  3650. *******
  3651. *******
  3652. *******
  3653. *******
  3654. *******
  3655. *******")]
  3656. [InlineData ("0 你 4", Alignment.Start, Alignment.Start, TextDirection.RightLeft_TopBottom, @"
  3657. 4 你 0*
  3658. *******
  3659. *******
  3660. *******
  3661. *******
  3662. *******
  3663. *******")]
  3664. [InlineData ("0 你 4", Alignment.End, Alignment.Start, TextDirection.RightLeft_TopBottom, @"
  3665. *4 你 0
  3666. *******
  3667. *******
  3668. *******
  3669. *******
  3670. *******
  3671. *******")]
  3672. [InlineData ("0 你 4", Alignment.Center, Alignment.Start, TextDirection.RightLeft_TopBottom, @"
  3673. 4 你 0*
  3674. *******
  3675. *******
  3676. *******
  3677. *******
  3678. *******
  3679. *******")]
  3680. [InlineData ("0 你 4", Alignment.Fill, Alignment.Start, TextDirection.RightLeft_TopBottom, @"
  3681. 4 你 0
  3682. *******
  3683. *******
  3684. *******
  3685. *******
  3686. *******
  3687. *******")]
  3688. // RightLeft_BottomTop
  3689. [InlineData ("0 2 4", Alignment.Start, Alignment.Start, TextDirection.RightLeft_BottomTop, @"
  3690. 4 2 0**
  3691. *******
  3692. *******
  3693. *******
  3694. *******
  3695. *******
  3696. *******")]
  3697. [InlineData ("0 2 4", Alignment.End, Alignment.Start, TextDirection.RightLeft_BottomTop, @"
  3698. **4 2 0
  3699. *******
  3700. *******
  3701. *******
  3702. *******
  3703. *******
  3704. *******")]
  3705. [InlineData ("0 2 4", Alignment.Center, Alignment.Start, TextDirection.RightLeft_BottomTop, @"
  3706. *4 2 0*
  3707. *******
  3708. *******
  3709. *******
  3710. *******
  3711. *******
  3712. *******")]
  3713. [InlineData ("0 2 4", Alignment.Fill, Alignment.Start, TextDirection.RightLeft_BottomTop, @"
  3714. 4 2 0
  3715. *******
  3716. *******
  3717. *******
  3718. *******
  3719. *******
  3720. *******")]
  3721. [InlineData ("0 你 4", Alignment.Start, Alignment.Start, TextDirection.RightLeft_BottomTop, @"
  3722. 4 你 0*
  3723. *******
  3724. *******
  3725. *******
  3726. *******
  3727. *******
  3728. *******")]
  3729. [InlineData ("0 你 4", Alignment.End, Alignment.Start, TextDirection.RightLeft_BottomTop, @"
  3730. *4 你 0
  3731. *******
  3732. *******
  3733. *******
  3734. *******
  3735. *******
  3736. *******")]
  3737. [InlineData ("0 你 4", Alignment.Center, Alignment.Start, TextDirection.RightLeft_BottomTop, @"
  3738. 4 你 0*
  3739. *******
  3740. *******
  3741. *******
  3742. *******
  3743. *******
  3744. *******")]
  3745. [InlineData ("0 你 4", Alignment.Fill, Alignment.Start, TextDirection.RightLeft_BottomTop, @"
  3746. 4 你 0
  3747. *******
  3748. *******
  3749. *******
  3750. *******
  3751. *******
  3752. *******")]
  3753. // Horizontal with Alignment.End
  3754. // LeftRight_TopBottom
  3755. [InlineData ("0 2 4", Alignment.Start, Alignment.End, TextDirection.LeftRight_TopBottom, @"
  3756. *******
  3757. *******
  3758. *******
  3759. *******
  3760. *******
  3761. *******
  3762. 0 2 4**")]
  3763. [InlineData ("0 2 4", Alignment.End, Alignment.End, TextDirection.LeftRight_TopBottom, @"
  3764. *******
  3765. *******
  3766. *******
  3767. *******
  3768. *******
  3769. *******
  3770. **0 2 4")]
  3771. [InlineData ("0 2 4", Alignment.Center, Alignment.End, TextDirection.LeftRight_TopBottom, @"
  3772. *******
  3773. *******
  3774. *******
  3775. *******
  3776. *******
  3777. *******
  3778. *0 2 4*")]
  3779. [InlineData ("0 2 4", Alignment.Fill, Alignment.End, TextDirection.LeftRight_TopBottom, @"
  3780. *******
  3781. *******
  3782. *******
  3783. *******
  3784. *******
  3785. *******
  3786. 0 2 4")]
  3787. [InlineData ("0 你 4", Alignment.Start, Alignment.End, TextDirection.LeftRight_TopBottom, @"
  3788. *******
  3789. *******
  3790. *******
  3791. *******
  3792. *******
  3793. *******
  3794. 0 你 4*")]
  3795. [InlineData ("0 你 4", Alignment.End, Alignment.End, TextDirection.LeftRight_TopBottom, @"
  3796. *******
  3797. *******
  3798. *******
  3799. *******
  3800. *******
  3801. *******
  3802. *0 你 4")]
  3803. [InlineData ("0 你 4", Alignment.Center, Alignment.End, TextDirection.LeftRight_TopBottom, @"
  3804. *******
  3805. *******
  3806. *******
  3807. *******
  3808. *******
  3809. *******
  3810. 0 你 4*")]
  3811. [InlineData ("0 你 4", Alignment.Fill, Alignment.End, TextDirection.LeftRight_TopBottom, @"
  3812. *******
  3813. *******
  3814. *******
  3815. *******
  3816. *******
  3817. *******
  3818. 0 你 4")]
  3819. // LeftRight_BottomTop
  3820. [InlineData ("0 2 4", Alignment.Start, Alignment.End, TextDirection.LeftRight_BottomTop, @"
  3821. *******
  3822. *******
  3823. *******
  3824. *******
  3825. *******
  3826. *******
  3827. 0 2 4**")]
  3828. [InlineData ("0 2 4", Alignment.End, Alignment.End, TextDirection.LeftRight_BottomTop, @"
  3829. *******
  3830. *******
  3831. *******
  3832. *******
  3833. *******
  3834. *******
  3835. **0 2 4")]
  3836. [InlineData ("0 2 4", Alignment.Center, Alignment.End, TextDirection.LeftRight_BottomTop, @"
  3837. *******
  3838. *******
  3839. *******
  3840. *******
  3841. *******
  3842. *******
  3843. *0 2 4*")]
  3844. [InlineData ("0 2 4", Alignment.Fill, Alignment.End, TextDirection.LeftRight_BottomTop, @"
  3845. *******
  3846. *******
  3847. *******
  3848. *******
  3849. *******
  3850. *******
  3851. 0 2 4")]
  3852. [InlineData ("0 你 4", Alignment.Start, Alignment.End, TextDirection.LeftRight_BottomTop, @"
  3853. *******
  3854. *******
  3855. *******
  3856. *******
  3857. *******
  3858. *******
  3859. 0 你 4*")]
  3860. [InlineData ("0 你 4", Alignment.End, Alignment.End, TextDirection.LeftRight_BottomTop, @"
  3861. *******
  3862. *******
  3863. *******
  3864. *******
  3865. *******
  3866. *******
  3867. *0 你 4")]
  3868. [InlineData ("0 你 4", Alignment.Center, Alignment.End, TextDirection.LeftRight_BottomTop, @"
  3869. *******
  3870. *******
  3871. *******
  3872. *******
  3873. *******
  3874. *******
  3875. 0 你 4*")]
  3876. [InlineData ("0 你 4", Alignment.Fill, Alignment.End, TextDirection.LeftRight_BottomTop, @"
  3877. *******
  3878. *******
  3879. *******
  3880. *******
  3881. *******
  3882. *******
  3883. 0 你 4")]
  3884. // RightLeft_TopBottom
  3885. [InlineData ("0 2 4", Alignment.Start, Alignment.End, TextDirection.RightLeft_TopBottom, @"
  3886. *******
  3887. *******
  3888. *******
  3889. *******
  3890. *******
  3891. *******
  3892. 4 2 0**")]
  3893. [InlineData ("0 2 4", Alignment.End, Alignment.End, TextDirection.RightLeft_TopBottom, @"
  3894. *******
  3895. *******
  3896. *******
  3897. *******
  3898. *******
  3899. *******
  3900. **4 2 0")]
  3901. [InlineData ("0 2 4", Alignment.Center, Alignment.End, TextDirection.RightLeft_TopBottom, @"
  3902. *******
  3903. *******
  3904. *******
  3905. *******
  3906. *******
  3907. *******
  3908. *4 2 0*")]
  3909. [InlineData ("0 2 4", Alignment.Fill, Alignment.End, TextDirection.RightLeft_TopBottom, @"
  3910. *******
  3911. *******
  3912. *******
  3913. *******
  3914. *******
  3915. *******
  3916. 4 2 0")]
  3917. [InlineData ("0 你 4", Alignment.Start, Alignment.End, TextDirection.RightLeft_TopBottom, @"
  3918. *******
  3919. *******
  3920. *******
  3921. *******
  3922. *******
  3923. *******
  3924. 4 你 0*")]
  3925. [InlineData ("0 你 4", Alignment.End, Alignment.End, TextDirection.RightLeft_TopBottom, @"
  3926. *******
  3927. *******
  3928. *******
  3929. *******
  3930. *******
  3931. *******
  3932. *4 你 0")]
  3933. [InlineData ("0 你 4", Alignment.Center, Alignment.End, TextDirection.RightLeft_TopBottom, @"
  3934. *******
  3935. *******
  3936. *******
  3937. *******
  3938. *******
  3939. *******
  3940. 4 你 0*")]
  3941. [InlineData ("0 你 4", Alignment.Fill, Alignment.End, TextDirection.RightLeft_TopBottom, @"
  3942. *******
  3943. *******
  3944. *******
  3945. *******
  3946. *******
  3947. *******
  3948. 4 你 0")]
  3949. // RightLeft_BottomTop
  3950. [InlineData ("0 2 4", Alignment.Start, Alignment.End, TextDirection.RightLeft_BottomTop, @"
  3951. *******
  3952. *******
  3953. *******
  3954. *******
  3955. *******
  3956. *******
  3957. 4 2 0**")]
  3958. [InlineData ("0 2 4", Alignment.End, Alignment.End, TextDirection.RightLeft_BottomTop, @"
  3959. *******
  3960. *******
  3961. *******
  3962. *******
  3963. *******
  3964. *******
  3965. **4 2 0")]
  3966. [InlineData ("0 2 4", Alignment.Center, Alignment.End, TextDirection.RightLeft_BottomTop, @"
  3967. *******
  3968. *******
  3969. *******
  3970. *******
  3971. *******
  3972. *******
  3973. *4 2 0*")]
  3974. [InlineData ("0 2 4", Alignment.Fill, Alignment.End, TextDirection.RightLeft_BottomTop, @"
  3975. *******
  3976. *******
  3977. *******
  3978. *******
  3979. *******
  3980. *******
  3981. 4 2 0")]
  3982. [InlineData ("0 你 4", Alignment.Start, Alignment.End, TextDirection.RightLeft_BottomTop, @"
  3983. *******
  3984. *******
  3985. *******
  3986. *******
  3987. *******
  3988. *******
  3989. 4 你 0*")]
  3990. [InlineData ("0 你 4", Alignment.End, Alignment.End, TextDirection.RightLeft_BottomTop, @"
  3991. *******
  3992. *******
  3993. *******
  3994. *******
  3995. *******
  3996. *******
  3997. *4 你 0")]
  3998. [InlineData ("0 你 4", Alignment.Center, Alignment.End, TextDirection.RightLeft_BottomTop, @"
  3999. *******
  4000. *******
  4001. *******
  4002. *******
  4003. *******
  4004. *******
  4005. 4 你 0*")]
  4006. [InlineData ("0 你 4", Alignment.Fill, Alignment.End, TextDirection.RightLeft_BottomTop, @"
  4007. *******
  4008. *******
  4009. *******
  4010. *******
  4011. *******
  4012. *******
  4013. 4 你 0")]
  4014. // Horizontal with alignment.Centered
  4015. // LeftRight_TopBottom
  4016. [InlineData ("0 2 4", Alignment.Start, Alignment.Center, TextDirection.LeftRight_TopBottom, @"
  4017. *******
  4018. *******
  4019. *******
  4020. 0 2 4**
  4021. *******
  4022. *******
  4023. *******")]
  4024. [InlineData ("0 2 4", Alignment.End, Alignment.Center, TextDirection.LeftRight_TopBottom, @"
  4025. *******
  4026. *******
  4027. *******
  4028. **0 2 4
  4029. *******
  4030. *******
  4031. *******")]
  4032. [InlineData ("0 2 4", Alignment.Center, Alignment.Center, TextDirection.LeftRight_TopBottom, @"
  4033. *******
  4034. *******
  4035. *******
  4036. *0 2 4*
  4037. *******
  4038. *******
  4039. *******")]
  4040. [InlineData ("0 2 4", Alignment.Fill, Alignment.Center, TextDirection.LeftRight_TopBottom, @"
  4041. *******
  4042. *******
  4043. *******
  4044. 0 2 4
  4045. *******
  4046. *******
  4047. *******")]
  4048. [InlineData ("0 你 4", Alignment.Start, Alignment.Center, TextDirection.LeftRight_TopBottom, @"
  4049. *******
  4050. *******
  4051. *******
  4052. 0 你 4*
  4053. *******
  4054. *******
  4055. *******")]
  4056. [InlineData ("0 你 4", Alignment.End, Alignment.Center, TextDirection.LeftRight_TopBottom, @"
  4057. *******
  4058. *******
  4059. *******
  4060. *0 你 4
  4061. *******
  4062. *******
  4063. *******")]
  4064. [InlineData ("0 你 4", Alignment.Center, Alignment.Center, TextDirection.LeftRight_TopBottom, @"
  4065. *******
  4066. *******
  4067. *******
  4068. 0 你 4*
  4069. *******
  4070. *******
  4071. *******")]
  4072. [InlineData ("0 你 4", Alignment.Fill, Alignment.Center, TextDirection.LeftRight_TopBottom, @"
  4073. *******
  4074. *******
  4075. *******
  4076. 0 你 4
  4077. *******
  4078. *******
  4079. *******")]
  4080. // LeftRight_BottomTop
  4081. [InlineData ("0 2 4", Alignment.Start, Alignment.Center, TextDirection.LeftRight_BottomTop, @"
  4082. *******
  4083. *******
  4084. *******
  4085. 0 2 4**
  4086. *******
  4087. *******
  4088. *******")]
  4089. [InlineData ("0 2 4", Alignment.End, Alignment.Center, TextDirection.LeftRight_BottomTop, @"
  4090. *******
  4091. *******
  4092. *******
  4093. **0 2 4
  4094. *******
  4095. *******
  4096. *******")]
  4097. [InlineData ("0 2 4", Alignment.Center, Alignment.Center, TextDirection.LeftRight_BottomTop, @"
  4098. *******
  4099. *******
  4100. *******
  4101. *0 2 4*
  4102. *******
  4103. *******
  4104. *******")]
  4105. [InlineData ("0 2 4", Alignment.Fill, Alignment.Center, TextDirection.LeftRight_BottomTop, @"
  4106. *******
  4107. *******
  4108. *******
  4109. 0 2 4
  4110. *******
  4111. *******
  4112. *******")]
  4113. [InlineData ("0 你 4", Alignment.Start, Alignment.Center, TextDirection.LeftRight_BottomTop, @"
  4114. *******
  4115. *******
  4116. *******
  4117. 0 你 4*
  4118. *******
  4119. *******
  4120. *******")]
  4121. [InlineData ("0 你 4", Alignment.End, Alignment.Center, TextDirection.LeftRight_BottomTop, @"
  4122. *******
  4123. *******
  4124. *******
  4125. *0 你 4
  4126. *******
  4127. *******
  4128. *******")]
  4129. [InlineData ("0 你 4", Alignment.Center, Alignment.Center, TextDirection.LeftRight_BottomTop, @"
  4130. *******
  4131. *******
  4132. *******
  4133. 0 你 4*
  4134. *******
  4135. *******
  4136. *******")]
  4137. [InlineData ("0 你 4", Alignment.Fill, Alignment.Center, TextDirection.LeftRight_BottomTop, @"
  4138. *******
  4139. *******
  4140. *******
  4141. 0 你 4
  4142. *******
  4143. *******
  4144. *******")]
  4145. // RightLeft_TopBottom
  4146. [InlineData ("0 2 4", Alignment.Start, Alignment.Center, TextDirection.RightLeft_TopBottom, @"
  4147. *******
  4148. *******
  4149. *******
  4150. 4 2 0**
  4151. *******
  4152. *******
  4153. *******")]
  4154. [InlineData ("0 2 4", Alignment.End, Alignment.Center, TextDirection.RightLeft_TopBottom, @"
  4155. *******
  4156. *******
  4157. *******
  4158. **4 2 0
  4159. *******
  4160. *******
  4161. *******")]
  4162. [InlineData ("0 2 4", Alignment.Center, Alignment.Center, TextDirection.RightLeft_TopBottom, @"
  4163. *******
  4164. *******
  4165. *******
  4166. *4 2 0*
  4167. *******
  4168. *******
  4169. *******")]
  4170. [InlineData ("0 2 4", Alignment.Fill, Alignment.Center, TextDirection.RightLeft_TopBottom, @"
  4171. *******
  4172. *******
  4173. *******
  4174. 4 2 0
  4175. *******
  4176. *******
  4177. *******")]
  4178. [InlineData ("0 你 4", Alignment.Start, Alignment.Center, TextDirection.RightLeft_TopBottom, @"
  4179. *******
  4180. *******
  4181. *******
  4182. 4 你 0*
  4183. *******
  4184. *******
  4185. *******")]
  4186. [InlineData ("0 你 4", Alignment.End, Alignment.Center, TextDirection.RightLeft_TopBottom, @"
  4187. *******
  4188. *******
  4189. *******
  4190. *4 你 0
  4191. *******
  4192. *******
  4193. *******")]
  4194. [InlineData ("0 你 4", Alignment.Center, Alignment.Center, TextDirection.RightLeft_TopBottom, @"
  4195. *******
  4196. *******
  4197. *******
  4198. 4 你 0*
  4199. *******
  4200. *******
  4201. *******")]
  4202. [InlineData ("0 你 4", Alignment.Fill, Alignment.Center, TextDirection.RightLeft_TopBottom, @"
  4203. *******
  4204. *******
  4205. *******
  4206. 4 你 0
  4207. *******
  4208. *******
  4209. *******")]
  4210. // RightLeft_BottomTop
  4211. [InlineData ("0 2 4", Alignment.Start, Alignment.Center, TextDirection.RightLeft_BottomTop, @"
  4212. *******
  4213. *******
  4214. *******
  4215. 4 2 0**
  4216. *******
  4217. *******
  4218. *******")]
  4219. [InlineData ("0 2 4", Alignment.End, Alignment.Center, TextDirection.RightLeft_BottomTop, @"
  4220. *******
  4221. *******
  4222. *******
  4223. **4 2 0
  4224. *******
  4225. *******
  4226. *******")]
  4227. [InlineData ("0 2 4", Alignment.Center, Alignment.Center, TextDirection.RightLeft_BottomTop, @"
  4228. *******
  4229. *******
  4230. *******
  4231. *4 2 0*
  4232. *******
  4233. *******
  4234. *******")]
  4235. [InlineData ("0 2 4", Alignment.Fill, Alignment.Center, TextDirection.RightLeft_BottomTop, @"
  4236. *******
  4237. *******
  4238. *******
  4239. 4 2 0
  4240. *******
  4241. *******
  4242. *******")]
  4243. [InlineData ("0 你 4", Alignment.Start, Alignment.Center, TextDirection.RightLeft_BottomTop, @"
  4244. *******
  4245. *******
  4246. *******
  4247. 4 你 0*
  4248. *******
  4249. *******
  4250. *******")]
  4251. [InlineData ("0 你 4", Alignment.End, Alignment.Center, TextDirection.RightLeft_BottomTop, @"
  4252. *******
  4253. *******
  4254. *******
  4255. *4 你 0
  4256. *******
  4257. *******
  4258. *******")]
  4259. [InlineData ("0 你 4", Alignment.Center, Alignment.Center, TextDirection.RightLeft_BottomTop, @"
  4260. *******
  4261. *******
  4262. *******
  4263. 4 你 0*
  4264. *******
  4265. *******
  4266. *******")]
  4267. [InlineData ("0 你 4", Alignment.Fill, Alignment.Center, TextDirection.RightLeft_BottomTop, @"
  4268. *******
  4269. *******
  4270. *******
  4271. 4 你 0
  4272. *******
  4273. *******
  4274. *******")]
  4275. // Horizontal with alignment.Justified
  4276. // LeftRight_TopBottom
  4277. [InlineData ("0 2 4", Alignment.Start, Alignment.Fill, TextDirection.LeftRight_TopBottom, @"
  4278. 0 2 4**
  4279. *******
  4280. *******
  4281. *******
  4282. *******
  4283. *******
  4284. *******")]
  4285. [InlineData ("0 2 4", Alignment.End, Alignment.Fill, TextDirection.LeftRight_TopBottom, @"
  4286. **0 2 4
  4287. *******
  4288. *******
  4289. *******
  4290. *******
  4291. *******
  4292. *******")]
  4293. [InlineData ("0 2 4", Alignment.Center, Alignment.Fill, TextDirection.LeftRight_TopBottom, @"
  4294. *0 2 4*
  4295. *******
  4296. *******
  4297. *******
  4298. *******
  4299. *******
  4300. *******")]
  4301. [InlineData ("0 2 4", Alignment.Fill, Alignment.Fill, TextDirection.LeftRight_TopBottom, @"
  4302. 0 2 4
  4303. *******
  4304. *******
  4305. *******
  4306. *******
  4307. *******
  4308. *******")]
  4309. [InlineData ("0 你 4", Alignment.Start, Alignment.Fill, TextDirection.LeftRight_TopBottom, @"
  4310. 0 你 4*
  4311. *******
  4312. *******
  4313. *******
  4314. *******
  4315. *******
  4316. *******")]
  4317. [InlineData ("0 你 4", Alignment.End, Alignment.Fill, TextDirection.LeftRight_TopBottom, @"
  4318. *0 你 4
  4319. *******
  4320. *******
  4321. *******
  4322. *******
  4323. *******
  4324. *******")]
  4325. [InlineData ("0 你 4", Alignment.Center, Alignment.Fill, TextDirection.LeftRight_TopBottom, @"
  4326. 0 你 4*
  4327. *******
  4328. *******
  4329. *******
  4330. *******
  4331. *******
  4332. *******")]
  4333. [InlineData ("0 你 4", Alignment.Fill, Alignment.Fill, TextDirection.LeftRight_TopBottom, @"
  4334. 0 你 4
  4335. *******
  4336. *******
  4337. *******
  4338. *******
  4339. *******
  4340. *******")]
  4341. // LeftRight_BottomTop
  4342. [InlineData ("0 2 4", Alignment.Start, Alignment.Fill, TextDirection.LeftRight_BottomTop, @"
  4343. 0 2 4**
  4344. *******
  4345. *******
  4346. *******
  4347. *******
  4348. *******
  4349. *******")]
  4350. [InlineData ("0 2 4", Alignment.End, Alignment.Fill, TextDirection.LeftRight_BottomTop, @"
  4351. **0 2 4
  4352. *******
  4353. *******
  4354. *******
  4355. *******
  4356. *******
  4357. *******")]
  4358. [InlineData ("0 2 4", Alignment.Center, Alignment.Fill, TextDirection.LeftRight_BottomTop, @"
  4359. *0 2 4*
  4360. *******
  4361. *******
  4362. *******
  4363. *******
  4364. *******
  4365. *******")]
  4366. [InlineData ("0 2 4", Alignment.Fill, Alignment.Fill, TextDirection.LeftRight_BottomTop, @"
  4367. 0 2 4
  4368. *******
  4369. *******
  4370. *******
  4371. *******
  4372. *******
  4373. *******")]
  4374. [InlineData ("0 你 4", Alignment.Start, Alignment.Fill, TextDirection.LeftRight_BottomTop, @"
  4375. 0 你 4*
  4376. *******
  4377. *******
  4378. *******
  4379. *******
  4380. *******
  4381. *******")]
  4382. [InlineData ("0 你 4", Alignment.End, Alignment.Fill, TextDirection.LeftRight_BottomTop, @"
  4383. *0 你 4
  4384. *******
  4385. *******
  4386. *******
  4387. *******
  4388. *******
  4389. *******")]
  4390. [InlineData ("0 你 4", Alignment.Center, Alignment.Fill, TextDirection.LeftRight_BottomTop, @"
  4391. 0 你 4*
  4392. *******
  4393. *******
  4394. *******
  4395. *******
  4396. *******
  4397. *******")]
  4398. [InlineData ("0 你 4", Alignment.Fill, Alignment.Fill, TextDirection.LeftRight_BottomTop, @"
  4399. 0 你 4
  4400. *******
  4401. *******
  4402. *******
  4403. *******
  4404. *******
  4405. *******")]
  4406. // RightLeft_TopBottom
  4407. [InlineData ("0 2 4", Alignment.Start, Alignment.Fill, TextDirection.RightLeft_TopBottom, @"
  4408. 4 2 0**
  4409. *******
  4410. *******
  4411. *******
  4412. *******
  4413. *******
  4414. *******")]
  4415. [InlineData ("0 2 4", Alignment.End, Alignment.Fill, TextDirection.RightLeft_TopBottom, @"
  4416. **4 2 0
  4417. *******
  4418. *******
  4419. *******
  4420. *******
  4421. *******
  4422. *******")]
  4423. [InlineData ("0 2 4", Alignment.Center, Alignment.Fill, TextDirection.RightLeft_TopBottom, @"
  4424. *4 2 0*
  4425. *******
  4426. *******
  4427. *******
  4428. *******
  4429. *******
  4430. *******")]
  4431. [InlineData ("0 2 4", Alignment.Fill, Alignment.Fill, TextDirection.RightLeft_TopBottom, @"
  4432. 4 2 0
  4433. *******
  4434. *******
  4435. *******
  4436. *******
  4437. *******
  4438. *******")]
  4439. [InlineData ("0 你 4", Alignment.Start, Alignment.Fill, TextDirection.RightLeft_TopBottom, @"
  4440. 4 你 0*
  4441. *******
  4442. *******
  4443. *******
  4444. *******
  4445. *******
  4446. *******")]
  4447. [InlineData ("0 你 4", Alignment.End, Alignment.Fill, TextDirection.RightLeft_TopBottom, @"
  4448. *4 你 0
  4449. *******
  4450. *******
  4451. *******
  4452. *******
  4453. *******
  4454. *******")]
  4455. [InlineData ("0 你 4", Alignment.Center, Alignment.Fill, TextDirection.RightLeft_TopBottom, @"
  4456. 4 你 0*
  4457. *******
  4458. *******
  4459. *******
  4460. *******
  4461. *******
  4462. *******")]
  4463. [InlineData ("0 你 4", Alignment.Fill, Alignment.Fill, TextDirection.RightLeft_TopBottom, @"
  4464. 4 你 0
  4465. *******
  4466. *******
  4467. *******
  4468. *******
  4469. *******
  4470. *******")]
  4471. // RightLeft_BottomTop
  4472. [InlineData ("0 2 4", Alignment.Start, Alignment.Fill, TextDirection.RightLeft_BottomTop, @"
  4473. 4 2 0**
  4474. *******
  4475. *******
  4476. *******
  4477. *******
  4478. *******
  4479. *******")]
  4480. [InlineData ("0 2 4", Alignment.End, Alignment.Fill, TextDirection.RightLeft_BottomTop, @"
  4481. **4 2 0
  4482. *******
  4483. *******
  4484. *******
  4485. *******
  4486. *******
  4487. *******")]
  4488. [InlineData ("0 2 4", Alignment.Center, Alignment.Fill, TextDirection.RightLeft_BottomTop, @"
  4489. *4 2 0*
  4490. *******
  4491. *******
  4492. *******
  4493. *******
  4494. *******
  4495. *******")]
  4496. [InlineData ("0 2 4", Alignment.Fill, Alignment.Fill, TextDirection.RightLeft_BottomTop, @"
  4497. 4 2 0
  4498. *******
  4499. *******
  4500. *******
  4501. *******
  4502. *******
  4503. *******")]
  4504. [InlineData ("0 你 4", Alignment.Start, Alignment.Fill, TextDirection.RightLeft_BottomTop, @"
  4505. 4 你 0*
  4506. *******
  4507. *******
  4508. *******
  4509. *******
  4510. *******
  4511. *******")]
  4512. [InlineData ("0 你 4", Alignment.End, Alignment.Fill, TextDirection.RightLeft_BottomTop, @"
  4513. *4 你 0
  4514. *******
  4515. *******
  4516. *******
  4517. *******
  4518. *******
  4519. *******")]
  4520. [InlineData ("0 你 4", Alignment.Center, Alignment.Fill, TextDirection.RightLeft_BottomTop, @"
  4521. 4 你 0*
  4522. *******
  4523. *******
  4524. *******
  4525. *******
  4526. *******
  4527. *******")]
  4528. [InlineData ("0 你 4", Alignment.Fill, Alignment.Fill, TextDirection.RightLeft_BottomTop, @"
  4529. 4 你 0
  4530. *******
  4531. *******
  4532. *******
  4533. *******
  4534. *******
  4535. *******")]
  4536. // Vertical with alignment.Left
  4537. // TopBottom_LeftRight
  4538. [InlineData ("0 2 4", Alignment.Start, Alignment.Start, TextDirection.TopBottom_LeftRight, @"
  4539. 0******
  4540. ******
  4541. 2******
  4542. ******
  4543. 4******
  4544. *******
  4545. *******")]
  4546. [InlineData ("0 2 4", Alignment.Start, Alignment.End, TextDirection.TopBottom_LeftRight, @"
  4547. *******
  4548. *******
  4549. 0******
  4550. ******
  4551. 2******
  4552. ******
  4553. 4******")]
  4554. [InlineData ("0 2 4", Alignment.Start, Alignment.Center, TextDirection.TopBottom_LeftRight, @"
  4555. *******
  4556. 0******
  4557. ******
  4558. 2******
  4559. ******
  4560. 4******
  4561. *******")]
  4562. [InlineData ("0 2 4", Alignment.Start, Alignment.Fill, TextDirection.TopBottom_LeftRight, @"
  4563. 0******
  4564. ******
  4565. ******
  4566. 2******
  4567. ******
  4568. ******
  4569. 4******")]
  4570. [InlineData ("0 你 4", Alignment.Start, Alignment.Start, TextDirection.TopBottom_LeftRight, @"
  4571. 0******
  4572. ******
  4573. 你*****
  4574. ******
  4575. 4******
  4576. *******
  4577. *******")]
  4578. [InlineData ("0 你 4", Alignment.Start, Alignment.End, TextDirection.TopBottom_LeftRight, @"
  4579. *******
  4580. *******
  4581. 0******
  4582. ******
  4583. 你*****
  4584. ******
  4585. 4******")]
  4586. [InlineData ("0 你 4", Alignment.Start, Alignment.Center, TextDirection.TopBottom_LeftRight, @"
  4587. *******
  4588. 0******
  4589. ******
  4590. 你*****
  4591. ******
  4592. 4******
  4593. *******")]
  4594. [InlineData ("0 你 4", Alignment.Start, Alignment.Fill, TextDirection.TopBottom_LeftRight, @"
  4595. 0******
  4596. ******
  4597. ******
  4598. 你*****
  4599. ******
  4600. ******
  4601. 4******")]
  4602. // TopBottom_RightLeft
  4603. [InlineData ("0 2 4", Alignment.Start, Alignment.Start, TextDirection.TopBottom_RightLeft, @"
  4604. 0******
  4605. ******
  4606. 2******
  4607. ******
  4608. 4******
  4609. *******
  4610. *******")]
  4611. [InlineData ("0 2 4", Alignment.Start, Alignment.End, TextDirection.TopBottom_RightLeft, @"
  4612. *******
  4613. *******
  4614. 0******
  4615. ******
  4616. 2******
  4617. ******
  4618. 4******")]
  4619. [InlineData ("0 2 4", Alignment.Start, Alignment.Center, TextDirection.TopBottom_RightLeft, @"
  4620. *******
  4621. 0******
  4622. ******
  4623. 2******
  4624. ******
  4625. 4******
  4626. *******")]
  4627. [InlineData ("0 2 4", Alignment.Start, Alignment.Fill, TextDirection.TopBottom_RightLeft, @"
  4628. 0******
  4629. ******
  4630. ******
  4631. 2******
  4632. ******
  4633. ******
  4634. 4******")]
  4635. [InlineData ("0 你 4", Alignment.Start, Alignment.Start, TextDirection.TopBottom_RightLeft, @"
  4636. 0******
  4637. ******
  4638. 你*****
  4639. ******
  4640. 4******
  4641. *******
  4642. *******")]
  4643. [InlineData ("0 你 4", Alignment.Start, Alignment.End, TextDirection.TopBottom_RightLeft, @"
  4644. *******
  4645. *******
  4646. 0******
  4647. ******
  4648. 你*****
  4649. ******
  4650. 4******")]
  4651. [InlineData ("0 你 4", Alignment.Start, Alignment.Center, TextDirection.TopBottom_RightLeft, @"
  4652. *******
  4653. 0******
  4654. ******
  4655. 你*****
  4656. ******
  4657. 4******
  4658. *******")]
  4659. [InlineData ("0 你 4", Alignment.Start, Alignment.Fill, TextDirection.TopBottom_RightLeft, @"
  4660. 0******
  4661. ******
  4662. ******
  4663. 你*****
  4664. ******
  4665. ******
  4666. 4******")]
  4667. // BottomTop_LeftRight
  4668. [InlineData ("0 2 4", Alignment.Start, Alignment.Start, TextDirection.BottomTop_LeftRight, @"
  4669. 4******
  4670. ******
  4671. 2******
  4672. ******
  4673. 0******
  4674. *******
  4675. *******")]
  4676. [InlineData ("0 2 4", Alignment.Start, Alignment.End, TextDirection.BottomTop_LeftRight, @"
  4677. *******
  4678. *******
  4679. 4******
  4680. ******
  4681. 2******
  4682. ******
  4683. 0******")]
  4684. [InlineData ("0 2 4", Alignment.Start, Alignment.Center, TextDirection.BottomTop_LeftRight, @"
  4685. *******
  4686. 4******
  4687. ******
  4688. 2******
  4689. ******
  4690. 0******
  4691. *******")]
  4692. [InlineData ("0 2 4", Alignment.Start, Alignment.Fill, TextDirection.BottomTop_LeftRight, @"
  4693. 4******
  4694. ******
  4695. ******
  4696. 2******
  4697. ******
  4698. ******
  4699. 0******")]
  4700. [InlineData ("0 你 4", Alignment.Start, Alignment.Start, TextDirection.BottomTop_LeftRight, @"
  4701. 4******
  4702. ******
  4703. 你*****
  4704. ******
  4705. 0******
  4706. *******
  4707. *******")]
  4708. [InlineData ("0 你 4", Alignment.Start, Alignment.End, TextDirection.BottomTop_LeftRight, @"
  4709. *******
  4710. *******
  4711. 4******
  4712. ******
  4713. 你*****
  4714. ******
  4715. 0******")]
  4716. [InlineData ("0 你 4", Alignment.Start, Alignment.Center, TextDirection.BottomTop_LeftRight, @"
  4717. *******
  4718. 4******
  4719. ******
  4720. 你*****
  4721. ******
  4722. 0******
  4723. *******")]
  4724. [InlineData ("0 你 4", Alignment.Start, Alignment.Fill, TextDirection.BottomTop_LeftRight, @"
  4725. 4******
  4726. ******
  4727. ******
  4728. 你*****
  4729. ******
  4730. ******
  4731. 0******")]
  4732. // BottomTop_RightLeft
  4733. [InlineData ("0 2 4", Alignment.Start, Alignment.Start, TextDirection.BottomTop_RightLeft, @"
  4734. 4******
  4735. ******
  4736. 2******
  4737. ******
  4738. 0******
  4739. *******
  4740. *******")]
  4741. [InlineData ("0 2 4", Alignment.Start, Alignment.End, TextDirection.BottomTop_RightLeft, @"
  4742. *******
  4743. *******
  4744. 4******
  4745. ******
  4746. 2******
  4747. ******
  4748. 0******")]
  4749. [InlineData ("0 2 4", Alignment.Start, Alignment.Center, TextDirection.BottomTop_RightLeft, @"
  4750. *******
  4751. 4******
  4752. ******
  4753. 2******
  4754. ******
  4755. 0******
  4756. *******")]
  4757. [InlineData ("0 2 4", Alignment.Start, Alignment.Fill, TextDirection.BottomTop_RightLeft, @"
  4758. 4******
  4759. ******
  4760. ******
  4761. 2******
  4762. ******
  4763. ******
  4764. 0******")]
  4765. [InlineData ("0 你 4", Alignment.Start, Alignment.Start, TextDirection.BottomTop_RightLeft, @"
  4766. 4******
  4767. ******
  4768. 你*****
  4769. ******
  4770. 0******
  4771. *******
  4772. *******")]
  4773. [InlineData ("0 你 4", Alignment.Start, Alignment.End, TextDirection.BottomTop_RightLeft, @"
  4774. *******
  4775. *******
  4776. 4******
  4777. ******
  4778. 你*****
  4779. ******
  4780. 0******")]
  4781. [InlineData ("0 你 4", Alignment.Start, Alignment.Center, TextDirection.BottomTop_RightLeft, @"
  4782. *******
  4783. 4******
  4784. ******
  4785. 你*****
  4786. ******
  4787. 0******
  4788. *******")]
  4789. [InlineData ("0 你 4", Alignment.Start, Alignment.Fill, TextDirection.BottomTop_RightLeft, @"
  4790. 4******
  4791. ******
  4792. ******
  4793. 你*****
  4794. ******
  4795. ******
  4796. 0******")]
  4797. // Vertical with alignment.Right
  4798. // TopBottom_LeftRight
  4799. [InlineData ("0 2 4", Alignment.End, Alignment.Start, TextDirection.TopBottom_LeftRight, @"
  4800. ******0
  4801. ******
  4802. ******2
  4803. ******
  4804. ******4
  4805. *******
  4806. *******")]
  4807. [InlineData ("0 2 4", Alignment.End, Alignment.End, TextDirection.TopBottom_LeftRight, @"
  4808. *******
  4809. *******
  4810. ******0
  4811. ******
  4812. ******2
  4813. ******
  4814. ******4")]
  4815. [InlineData ("0 2 4", Alignment.End, Alignment.Center, TextDirection.TopBottom_LeftRight, @"
  4816. *******
  4817. ******0
  4818. ******
  4819. ******2
  4820. ******
  4821. ******4
  4822. *******")]
  4823. [InlineData ("0 2 4", Alignment.End, Alignment.Fill, TextDirection.TopBottom_LeftRight, @"
  4824. ******0
  4825. ******
  4826. ******
  4827. ******2
  4828. ******
  4829. ******
  4830. ******4")]
  4831. [InlineData ("0 你 4", Alignment.End, Alignment.Start, TextDirection.TopBottom_LeftRight, @"
  4832. *****0*
  4833. ***** *
  4834. *****你
  4835. ***** *
  4836. *****4*
  4837. *******
  4838. *******")]
  4839. [InlineData ("0 你 4", Alignment.End, Alignment.End, TextDirection.TopBottom_LeftRight, @"
  4840. *******
  4841. *******
  4842. *****0*
  4843. ***** *
  4844. *****你
  4845. ***** *
  4846. *****4*")]
  4847. [InlineData ("0 你 4", Alignment.End, Alignment.Center, TextDirection.TopBottom_LeftRight, @"
  4848. *******
  4849. *****0*
  4850. ***** *
  4851. *****你
  4852. ***** *
  4853. *****4*
  4854. *******")]
  4855. [InlineData ("0 你 4", Alignment.End, Alignment.Fill, TextDirection.TopBottom_LeftRight, @"
  4856. *****0*
  4857. ***** *
  4858. ***** *
  4859. *****你
  4860. ***** *
  4861. ***** *
  4862. *****4*")]
  4863. // TopBottom_RightLeft
  4864. [InlineData ("0 2 4", Alignment.End, Alignment.Start, TextDirection.TopBottom_RightLeft, @"
  4865. ******0
  4866. ******
  4867. ******2
  4868. ******
  4869. ******4
  4870. *******
  4871. *******")]
  4872. [InlineData ("0 2 4", Alignment.End, Alignment.End, TextDirection.TopBottom_RightLeft, @"
  4873. *******
  4874. *******
  4875. ******0
  4876. ******
  4877. ******2
  4878. ******
  4879. ******4")]
  4880. [InlineData ("0 2 4", Alignment.End, Alignment.Center, TextDirection.TopBottom_RightLeft, @"
  4881. *******
  4882. ******0
  4883. ******
  4884. ******2
  4885. ******
  4886. ******4
  4887. *******")]
  4888. [InlineData ("0 2 4", Alignment.End, Alignment.Fill, TextDirection.TopBottom_RightLeft, @"
  4889. ******0
  4890. ******
  4891. ******
  4892. ******2
  4893. ******
  4894. ******
  4895. ******4")]
  4896. [InlineData ("0 你 4", Alignment.End, Alignment.Start, TextDirection.TopBottom_RightLeft, @"
  4897. *****0*
  4898. ***** *
  4899. *****你
  4900. ***** *
  4901. *****4*
  4902. *******
  4903. *******")]
  4904. [InlineData ("0 你 4", Alignment.End, Alignment.End, TextDirection.TopBottom_RightLeft, @"
  4905. *******
  4906. *******
  4907. *****0*
  4908. ***** *
  4909. *****你
  4910. ***** *
  4911. *****4*")]
  4912. [InlineData ("0 你 4", Alignment.End, Alignment.Center, TextDirection.TopBottom_RightLeft, @"
  4913. *******
  4914. *****0*
  4915. ***** *
  4916. *****你
  4917. ***** *
  4918. *****4*
  4919. *******")]
  4920. [InlineData ("0 你 4", Alignment.End, Alignment.Fill, TextDirection.TopBottom_RightLeft, @"
  4921. *****0*
  4922. ***** *
  4923. ***** *
  4924. *****你
  4925. ***** *
  4926. ***** *
  4927. *****4*")]
  4928. // BottomTop_LeftRight
  4929. [InlineData ("0 2 4", Alignment.End, Alignment.Start, TextDirection.BottomTop_LeftRight, @"
  4930. ******4
  4931. ******
  4932. ******2
  4933. ******
  4934. ******0
  4935. *******
  4936. *******")]
  4937. [InlineData ("0 2 4", Alignment.End, Alignment.End, TextDirection.BottomTop_LeftRight, @"
  4938. *******
  4939. *******
  4940. ******4
  4941. ******
  4942. ******2
  4943. ******
  4944. ******0")]
  4945. [InlineData ("0 2 4", Alignment.End, Alignment.Center, TextDirection.BottomTop_LeftRight, @"
  4946. *******
  4947. ******4
  4948. ******
  4949. ******2
  4950. ******
  4951. ******0
  4952. *******")]
  4953. [InlineData ("0 2 4", Alignment.End, Alignment.Fill, TextDirection.BottomTop_LeftRight, @"
  4954. ******4
  4955. ******
  4956. ******
  4957. ******2
  4958. ******
  4959. ******
  4960. ******0")]
  4961. [InlineData ("0 你 4", Alignment.End, Alignment.Start, TextDirection.BottomTop_LeftRight, @"
  4962. *****4*
  4963. ***** *
  4964. *****你
  4965. ***** *
  4966. *****0*
  4967. *******
  4968. *******")]
  4969. [InlineData ("0 你 4", Alignment.End, Alignment.End, TextDirection.BottomTop_LeftRight, @"
  4970. *******
  4971. *******
  4972. *****4*
  4973. ***** *
  4974. *****你
  4975. ***** *
  4976. *****0*")]
  4977. [InlineData ("0 你 4", Alignment.End, Alignment.Center, TextDirection.BottomTop_LeftRight, @"
  4978. *******
  4979. *****4*
  4980. ***** *
  4981. *****你
  4982. ***** *
  4983. *****0*
  4984. *******")]
  4985. [InlineData ("0 你 4", Alignment.End, Alignment.Fill, TextDirection.BottomTop_LeftRight, @"
  4986. *****4*
  4987. ***** *
  4988. ***** *
  4989. *****你
  4990. ***** *
  4991. ***** *
  4992. *****0*")]
  4993. // BottomTop_RightLeft
  4994. [InlineData ("0 2 4", Alignment.End, Alignment.Start, TextDirection.BottomTop_RightLeft, @"
  4995. ******4
  4996. ******
  4997. ******2
  4998. ******
  4999. ******0
  5000. *******
  5001. *******")]
  5002. [InlineData ("0 2 4", Alignment.End, Alignment.End, TextDirection.BottomTop_RightLeft, @"
  5003. *******
  5004. *******
  5005. ******4
  5006. ******
  5007. ******2
  5008. ******
  5009. ******0")]
  5010. [InlineData ("0 2 4", Alignment.End, Alignment.Center, TextDirection.BottomTop_RightLeft, @"
  5011. *******
  5012. ******4
  5013. ******
  5014. ******2
  5015. ******
  5016. ******0
  5017. *******")]
  5018. [InlineData ("0 2 4", Alignment.End, Alignment.Fill, TextDirection.BottomTop_RightLeft, @"
  5019. ******4
  5020. ******
  5021. ******
  5022. ******2
  5023. ******
  5024. ******
  5025. ******0")]
  5026. [InlineData ("0 你 4", Alignment.End, Alignment.Start, TextDirection.BottomTop_RightLeft, @"
  5027. *****4*
  5028. ***** *
  5029. *****你
  5030. ***** *
  5031. *****0*
  5032. *******
  5033. *******")]
  5034. [InlineData ("0 你 4", Alignment.End, Alignment.End, TextDirection.BottomTop_RightLeft, @"
  5035. *******
  5036. *******
  5037. *****4*
  5038. ***** *
  5039. *****你
  5040. ***** *
  5041. *****0*")]
  5042. [InlineData ("0 你 4", Alignment.End, Alignment.Center, TextDirection.BottomTop_RightLeft, @"
  5043. *******
  5044. *****4*
  5045. ***** *
  5046. *****你
  5047. ***** *
  5048. *****0*
  5049. *******")]
  5050. [InlineData ("0 你 4", Alignment.End, Alignment.Fill, TextDirection.BottomTop_RightLeft, @"
  5051. *****4*
  5052. ***** *
  5053. ***** *
  5054. *****你
  5055. ***** *
  5056. ***** *
  5057. *****0*")]
  5058. // Vertical with alignment.Centered
  5059. // TopBottom_LeftRight
  5060. [InlineData ("0 2 4", Alignment.Center, Alignment.Start, TextDirection.TopBottom_LeftRight, @"
  5061. ***0***
  5062. *** ***
  5063. ***2***
  5064. *** ***
  5065. ***4***
  5066. *******
  5067. *******")]
  5068. [InlineData ("0 2 4", Alignment.Center, Alignment.End, TextDirection.TopBottom_LeftRight, @"
  5069. *******
  5070. *******
  5071. ***0***
  5072. *** ***
  5073. ***2***
  5074. *** ***
  5075. ***4***")]
  5076. [InlineData ("0 2 4", Alignment.Center, Alignment.Center, TextDirection.TopBottom_LeftRight, @"
  5077. *******
  5078. ***0***
  5079. *** ***
  5080. ***2***
  5081. *** ***
  5082. ***4***
  5083. *******")]
  5084. [InlineData ("0 2 4", Alignment.Center, Alignment.Fill, TextDirection.TopBottom_LeftRight, @"
  5085. ***0***
  5086. *** ***
  5087. *** ***
  5088. ***2***
  5089. *** ***
  5090. *** ***
  5091. ***4***")]
  5092. [InlineData ("0 你 4", Alignment.Center, Alignment.Start, TextDirection.TopBottom_LeftRight, @"
  5093. **0****
  5094. ** ****
  5095. **你***
  5096. ** ****
  5097. **4****
  5098. *******
  5099. *******")]
  5100. [InlineData ("0 你 4", Alignment.Center, Alignment.End, TextDirection.TopBottom_LeftRight, @"
  5101. *******
  5102. *******
  5103. **0****
  5104. ** ****
  5105. **你***
  5106. ** ****
  5107. **4****")]
  5108. [InlineData ("0 你 4", Alignment.Center, Alignment.Center, TextDirection.TopBottom_LeftRight, @"
  5109. *******
  5110. **0****
  5111. ** ****
  5112. **你***
  5113. ** ****
  5114. **4****
  5115. *******")]
  5116. [InlineData ("0 你 4", Alignment.Center, Alignment.Fill, TextDirection.TopBottom_LeftRight, @"
  5117. **0****
  5118. ** ****
  5119. ** ****
  5120. **你***
  5121. ** ****
  5122. ** ****
  5123. **4****")]
  5124. // TopBottom_RightLeft
  5125. [InlineData ("0 2 4", Alignment.Center, Alignment.Start, TextDirection.TopBottom_RightLeft, @"
  5126. ***0***
  5127. *** ***
  5128. ***2***
  5129. *** ***
  5130. ***4***
  5131. *******
  5132. *******")]
  5133. [InlineData ("0 2 4", Alignment.Center, Alignment.End, TextDirection.TopBottom_RightLeft, @"
  5134. *******
  5135. *******
  5136. ***0***
  5137. *** ***
  5138. ***2***
  5139. *** ***
  5140. ***4***")]
  5141. [InlineData ("0 2 4", Alignment.Center, Alignment.Center, TextDirection.TopBottom_RightLeft, @"
  5142. *******
  5143. ***0***
  5144. *** ***
  5145. ***2***
  5146. *** ***
  5147. ***4***
  5148. *******")]
  5149. [InlineData ("0 2 4", Alignment.Center, Alignment.Fill, TextDirection.TopBottom_RightLeft, @"
  5150. ***0***
  5151. *** ***
  5152. *** ***
  5153. ***2***
  5154. *** ***
  5155. *** ***
  5156. ***4***")]
  5157. [InlineData ("0 你 4", Alignment.Center, Alignment.Start, TextDirection.TopBottom_RightLeft, @"
  5158. **0****
  5159. ** ****
  5160. **你***
  5161. ** ****
  5162. **4****
  5163. *******
  5164. *******")]
  5165. [InlineData ("0 你 4", Alignment.Center, Alignment.End, TextDirection.TopBottom_RightLeft, @"
  5166. *******
  5167. *******
  5168. **0****
  5169. ** ****
  5170. **你***
  5171. ** ****
  5172. **4****")]
  5173. [InlineData ("0 你 4", Alignment.Center, Alignment.Center, TextDirection.TopBottom_RightLeft, @"
  5174. *******
  5175. **0****
  5176. ** ****
  5177. **你***
  5178. ** ****
  5179. **4****
  5180. *******")]
  5181. [InlineData ("0 你 4", Alignment.Center, Alignment.Fill, TextDirection.TopBottom_RightLeft, @"
  5182. **0****
  5183. ** ****
  5184. ** ****
  5185. **你***
  5186. ** ****
  5187. ** ****
  5188. **4****")]
  5189. // BottomTop_LeftRight
  5190. [InlineData ("0 2 4", Alignment.Center, Alignment.Start, TextDirection.BottomTop_LeftRight, @"
  5191. ***4***
  5192. *** ***
  5193. ***2***
  5194. *** ***
  5195. ***0***
  5196. *******
  5197. *******")]
  5198. [InlineData ("0 2 4", Alignment.Center, Alignment.End, TextDirection.BottomTop_LeftRight, @"
  5199. *******
  5200. *******
  5201. ***4***
  5202. *** ***
  5203. ***2***
  5204. *** ***
  5205. ***0***")]
  5206. [InlineData ("0 2 4", Alignment.Center, Alignment.Center, TextDirection.BottomTop_LeftRight, @"
  5207. *******
  5208. ***4***
  5209. *** ***
  5210. ***2***
  5211. *** ***
  5212. ***0***
  5213. *******")]
  5214. [InlineData ("0 2 4", Alignment.Center, Alignment.Fill, TextDirection.BottomTop_LeftRight, @"
  5215. ***4***
  5216. *** ***
  5217. *** ***
  5218. ***2***
  5219. *** ***
  5220. *** ***
  5221. ***0***")]
  5222. [InlineData ("0 你 4", Alignment.Center, Alignment.Start, TextDirection.BottomTop_LeftRight, @"
  5223. **4****
  5224. ** ****
  5225. **你***
  5226. ** ****
  5227. **0****
  5228. *******
  5229. *******")]
  5230. [InlineData ("0 你 4", Alignment.Center, Alignment.End, TextDirection.BottomTop_LeftRight, @"
  5231. *******
  5232. *******
  5233. **4****
  5234. ** ****
  5235. **你***
  5236. ** ****
  5237. **0****")]
  5238. [InlineData ("0 你 4", Alignment.Center, Alignment.Center, TextDirection.BottomTop_LeftRight, @"
  5239. *******
  5240. **4****
  5241. ** ****
  5242. **你***
  5243. ** ****
  5244. **0****
  5245. *******")]
  5246. [InlineData ("0 你 4", Alignment.Center, Alignment.Fill, TextDirection.BottomTop_LeftRight, @"
  5247. **4****
  5248. ** ****
  5249. ** ****
  5250. **你***
  5251. ** ****
  5252. ** ****
  5253. **0****")]
  5254. // BottomTop_RightLeft
  5255. [InlineData ("0 2 4", Alignment.Center, Alignment.Start, TextDirection.BottomTop_RightLeft, @"
  5256. ***4***
  5257. *** ***
  5258. ***2***
  5259. *** ***
  5260. ***0***
  5261. *******
  5262. *******")]
  5263. [InlineData ("0 2 4", Alignment.Center, Alignment.End, TextDirection.BottomTop_RightLeft, @"
  5264. *******
  5265. *******
  5266. ***4***
  5267. *** ***
  5268. ***2***
  5269. *** ***
  5270. ***0***")]
  5271. [InlineData ("0 2 4", Alignment.Center, Alignment.Center, TextDirection.BottomTop_RightLeft, @"
  5272. *******
  5273. ***4***
  5274. *** ***
  5275. ***2***
  5276. *** ***
  5277. ***0***
  5278. *******")]
  5279. [InlineData ("0 2 4", Alignment.Center, Alignment.Fill, TextDirection.BottomTop_RightLeft, @"
  5280. ***4***
  5281. *** ***
  5282. *** ***
  5283. ***2***
  5284. *** ***
  5285. *** ***
  5286. ***0***")]
  5287. [InlineData ("0 你 4", Alignment.Center, Alignment.Start, TextDirection.BottomTop_RightLeft, @"
  5288. **4****
  5289. ** ****
  5290. **你***
  5291. ** ****
  5292. **0****
  5293. *******
  5294. *******")]
  5295. [InlineData ("0 你 4", Alignment.Center, Alignment.End, TextDirection.BottomTop_RightLeft, @"
  5296. *******
  5297. *******
  5298. **4****
  5299. ** ****
  5300. **你***
  5301. ** ****
  5302. **0****")]
  5303. [InlineData ("0 你 4", Alignment.Center, Alignment.Center, TextDirection.BottomTop_RightLeft, @"
  5304. *******
  5305. **4****
  5306. ** ****
  5307. **你***
  5308. ** ****
  5309. **0****
  5310. *******")]
  5311. [InlineData ("0 你 4", Alignment.Center, Alignment.Fill, TextDirection.BottomTop_RightLeft, @"
  5312. **4****
  5313. ** ****
  5314. ** ****
  5315. **你***
  5316. ** ****
  5317. ** ****
  5318. **0****")]
  5319. // Vertical with alignment.Justified
  5320. // TopBottom_LeftRight
  5321. [InlineData ("0 2 4", Alignment.Fill, Alignment.Start, TextDirection.TopBottom_LeftRight, @"
  5322. 0******
  5323. ******
  5324. 2******
  5325. ******
  5326. 4******
  5327. *******
  5328. *******")]
  5329. [InlineData ("0 2 4", Alignment.Fill, Alignment.End, TextDirection.TopBottom_LeftRight, @"
  5330. *******
  5331. *******
  5332. 0******
  5333. ******
  5334. 2******
  5335. ******
  5336. 4******")]
  5337. [InlineData ("0 2 4", Alignment.Fill, Alignment.Center, TextDirection.TopBottom_LeftRight, @"
  5338. *******
  5339. 0******
  5340. ******
  5341. 2******
  5342. ******
  5343. 4******
  5344. *******")]
  5345. [InlineData ("0 2 4", Alignment.Fill, Alignment.Fill, TextDirection.TopBottom_LeftRight, @"
  5346. 0******
  5347. ******
  5348. ******
  5349. 2******
  5350. ******
  5351. ******
  5352. 4******")]
  5353. [InlineData ("0 你 4", Alignment.Fill, Alignment.Start, TextDirection.TopBottom_LeftRight, @"
  5354. 0******
  5355. ******
  5356. 你*****
  5357. ******
  5358. 4******
  5359. *******
  5360. *******")]
  5361. [InlineData ("0 你 4", Alignment.Fill, Alignment.End, TextDirection.TopBottom_LeftRight, @"
  5362. *******
  5363. *******
  5364. 0******
  5365. ******
  5366. 你*****
  5367. ******
  5368. 4******")]
  5369. [InlineData ("0 你 4", Alignment.Fill, Alignment.Center, TextDirection.TopBottom_LeftRight, @"
  5370. *******
  5371. 0******
  5372. ******
  5373. 你*****
  5374. ******
  5375. 4******
  5376. *******")]
  5377. [InlineData ("0 你 4", Alignment.Fill, Alignment.Fill, TextDirection.TopBottom_LeftRight, @"
  5378. 0******
  5379. ******
  5380. ******
  5381. 你*****
  5382. ******
  5383. ******
  5384. 4******")]
  5385. // TopBottom_RightLeft
  5386. [InlineData ("0 2 4", Alignment.Fill, Alignment.Start, TextDirection.TopBottom_RightLeft, @"
  5387. 0******
  5388. ******
  5389. 2******
  5390. ******
  5391. 4******
  5392. *******
  5393. *******")]
  5394. [InlineData ("0 2 4", Alignment.Fill, Alignment.End, TextDirection.TopBottom_RightLeft, @"
  5395. *******
  5396. *******
  5397. 0******
  5398. ******
  5399. 2******
  5400. ******
  5401. 4******")]
  5402. [InlineData ("0 2 4", Alignment.Fill, Alignment.Center, TextDirection.TopBottom_RightLeft, @"
  5403. *******
  5404. 0******
  5405. ******
  5406. 2******
  5407. ******
  5408. 4******
  5409. *******")]
  5410. [InlineData ("0 2 4", Alignment.Fill, Alignment.Fill, TextDirection.TopBottom_RightLeft, @"
  5411. 0******
  5412. ******
  5413. ******
  5414. 2******
  5415. ******
  5416. ******
  5417. 4******")]
  5418. [InlineData ("0 你 4", Alignment.Fill, Alignment.Start, TextDirection.TopBottom_RightLeft, @"
  5419. 0******
  5420. ******
  5421. 你*****
  5422. ******
  5423. 4******
  5424. *******
  5425. *******")]
  5426. [InlineData ("0 你 4", Alignment.Fill, Alignment.End, TextDirection.TopBottom_RightLeft, @"
  5427. *******
  5428. *******
  5429. 0******
  5430. ******
  5431. 你*****
  5432. ******
  5433. 4******")]
  5434. [InlineData ("0 你 4", Alignment.Fill, Alignment.Center, TextDirection.TopBottom_RightLeft, @"
  5435. *******
  5436. 0******
  5437. ******
  5438. 你*****
  5439. ******
  5440. 4******
  5441. *******")]
  5442. [InlineData ("0 你 4", Alignment.Fill, Alignment.Fill, TextDirection.TopBottom_RightLeft, @"
  5443. 0******
  5444. ******
  5445. ******
  5446. 你*****
  5447. ******
  5448. ******
  5449. 4******")]
  5450. // BottomTop_LeftRight
  5451. [InlineData ("0 2 4", Alignment.Fill, Alignment.Start, TextDirection.BottomTop_LeftRight, @"
  5452. 4******
  5453. ******
  5454. 2******
  5455. ******
  5456. 0******
  5457. *******
  5458. *******")]
  5459. [InlineData ("0 2 4", Alignment.Fill, Alignment.End, TextDirection.BottomTop_LeftRight, @"
  5460. *******
  5461. *******
  5462. 4******
  5463. ******
  5464. 2******
  5465. ******
  5466. 0******")]
  5467. [InlineData ("0 2 4", Alignment.Fill, Alignment.Center, TextDirection.BottomTop_LeftRight, @"
  5468. *******
  5469. 4******
  5470. ******
  5471. 2******
  5472. ******
  5473. 0******
  5474. *******")]
  5475. [InlineData ("0 2 4", Alignment.Fill, Alignment.Fill, TextDirection.BottomTop_LeftRight, @"
  5476. 4******
  5477. ******
  5478. ******
  5479. 2******
  5480. ******
  5481. ******
  5482. 0******")]
  5483. [InlineData ("0 你 4", Alignment.Fill, Alignment.Start, TextDirection.BottomTop_LeftRight, @"
  5484. 4******
  5485. ******
  5486. 你*****
  5487. ******
  5488. 0******
  5489. *******
  5490. *******")]
  5491. [InlineData ("0 你 4", Alignment.Fill, Alignment.End, TextDirection.BottomTop_LeftRight, @"
  5492. *******
  5493. *******
  5494. 4******
  5495. ******
  5496. 你*****
  5497. ******
  5498. 0******")]
  5499. [InlineData ("0 你 4", Alignment.Fill, Alignment.Center, TextDirection.BottomTop_LeftRight, @"
  5500. *******
  5501. 4******
  5502. ******
  5503. 你*****
  5504. ******
  5505. 0******
  5506. *******")]
  5507. [InlineData ("0 你 4", Alignment.Fill, Alignment.Fill, TextDirection.BottomTop_LeftRight, @"
  5508. 4******
  5509. ******
  5510. ******
  5511. 你*****
  5512. ******
  5513. ******
  5514. 0******")]
  5515. // BottomTop_RightLeft
  5516. [InlineData ("0 2 4", Alignment.Fill, Alignment.Start, TextDirection.BottomTop_RightLeft, @"
  5517. 4******
  5518. ******
  5519. 2******
  5520. ******
  5521. 0******
  5522. *******
  5523. *******")]
  5524. [InlineData ("0 2 4", Alignment.Fill, Alignment.End, TextDirection.BottomTop_RightLeft, @"
  5525. *******
  5526. *******
  5527. 4******
  5528. ******
  5529. 2******
  5530. ******
  5531. 0******")]
  5532. [InlineData ("0 2 4", Alignment.Fill, Alignment.Center, TextDirection.BottomTop_RightLeft, @"
  5533. *******
  5534. 4******
  5535. ******
  5536. 2******
  5537. ******
  5538. 0******
  5539. *******")]
  5540. [InlineData ("0 2 4", Alignment.Fill, Alignment.Fill, TextDirection.BottomTop_RightLeft, @"
  5541. 4******
  5542. ******
  5543. ******
  5544. 2******
  5545. ******
  5546. ******
  5547. 0******")]
  5548. [InlineData ("0 你 4", Alignment.Fill, Alignment.Start, TextDirection.BottomTop_RightLeft, @"
  5549. 4******
  5550. ******
  5551. 你*****
  5552. ******
  5553. 0******
  5554. *******
  5555. *******")]
  5556. [InlineData ("0 你 4", Alignment.Fill, Alignment.End, TextDirection.BottomTop_RightLeft, @"
  5557. *******
  5558. *******
  5559. 4******
  5560. ******
  5561. 你*****
  5562. ******
  5563. 0******")]
  5564. [InlineData ("0 你 4", Alignment.Fill, Alignment.Center, TextDirection.BottomTop_RightLeft, @"
  5565. *******
  5566. 4******
  5567. ******
  5568. 你*****
  5569. ******
  5570. 0******
  5571. *******")]
  5572. [InlineData ("0 你 4", Alignment.Fill, Alignment.Fill, TextDirection.BottomTop_RightLeft, @"
  5573. 4******
  5574. ******
  5575. ******
  5576. 你*****
  5577. ******
  5578. ******
  5579. 0******")]
  5580. public void Draw_Text_Justification (string text, Alignment horizontalTextAlignment, Alignment alignment, TextDirection textDirection, string expectedText)
  5581. {
  5582. TextFormatter tf = new ()
  5583. {
  5584. Alignment = horizontalTextAlignment,
  5585. VerticalAlignment = alignment,
  5586. Direction = textDirection,
  5587. Size = new (7, 7),
  5588. Text = text
  5589. };
  5590. Application.Driver.FillRect (new Rectangle (0, 0, 7, 7), (Rune)'*');
  5591. tf.Draw (new Rectangle (0, 0, 7, 7), Attribute.Default, Attribute.Default);
  5592. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
  5593. }
  5594. #region FormatAndGetSizeTests
  5595. // TODO: Add multi-line examples
  5596. // TODO: Add other TextDirection examples
  5597. [Theory]
  5598. [SetupFakeDriver]
  5599. [InlineData ("界1234", 10, 10, TextDirection.LeftRight_TopBottom, 6, 1, @"界1234")]
  5600. [InlineData ("01234", 10, 10, TextDirection.LeftRight_TopBottom, 5, 1, @"01234")]
  5601. [InlineData ("界1234", 10, 10, TextDirection.TopBottom_LeftRight, 2, 5, """
  5602. 1
  5603. 2
  5604. 3
  5605. 4
  5606. """)]
  5607. [InlineData ("01234", 10, 10, TextDirection.TopBottom_LeftRight, 1, 5, """
  5608. 0
  5609. 1
  5610. 2
  5611. 3
  5612. 4
  5613. """)]
  5614. [InlineData ("界1234", 3, 3, TextDirection.LeftRight_TopBottom, 3, 2, """
  5615. 界1
  5616. 234
  5617. """)]
  5618. [InlineData ("01234", 3, 3, TextDirection.LeftRight_TopBottom, 3, 2, """
  5619. 012
  5620. 34
  5621. """)]
  5622. [InlineData ("界1234", 3, 3, TextDirection.TopBottom_LeftRight, 3, 3, """
  5623. 界3
  5624. 1 4
  5625. 2
  5626. """)]
  5627. [InlineData ("01234", 3, 3, TextDirection.TopBottom_LeftRight, 2, 3, """
  5628. 03
  5629. 14
  5630. 2
  5631. """)]
  5632. public void FormatAndGetSize_Returns_Correct_Size (string text, int width, int height, TextDirection direction, int expectedWidth, int expectedHeight, string expectedDraw)
  5633. {
  5634. TextFormatter tf = new ()
  5635. {
  5636. Direction = direction,
  5637. Size = new (width, height),
  5638. Text = text
  5639. };
  5640. Assert.True (tf.WordWrap);
  5641. Size size = tf.FormatAndGetSize ();
  5642. Assert.Equal (new (expectedWidth, expectedHeight), size);
  5643. tf.Draw (new (0, 0, width, height), Attribute.Default, Attribute.Default);
  5644. TestHelpers.AssertDriverContentsWithFrameAre (expectedDraw, _output);
  5645. }
  5646. [Theory]
  5647. [SetupFakeDriver]
  5648. [InlineData ("界1234", 10, 10, TextDirection.LeftRight_TopBottom, 6, 1, @"界1234")]
  5649. [InlineData ("01234", 10, 10, TextDirection.LeftRight_TopBottom, 5, 1, @"01234")]
  5650. [InlineData ("界1234", 10, 10, TextDirection.TopBottom_LeftRight, 2, 5, """
  5651. 1
  5652. 2
  5653. 3
  5654. 4
  5655. """)]
  5656. [InlineData ("01234", 10, 10, TextDirection.TopBottom_LeftRight, 1, 5, """
  5657. 0
  5658. 1
  5659. 2
  5660. 3
  5661. 4
  5662. """)]
  5663. [InlineData ("界1234", 3, 3, TextDirection.LeftRight_TopBottom, 3, 1, @"界1")]
  5664. [InlineData ("01234", 3, 3, TextDirection.LeftRight_TopBottom, 3, 1, @"012")]
  5665. [InlineData ("界1234", 3, 3, TextDirection.TopBottom_LeftRight, 2, 3, """
  5666. 1
  5667. 2
  5668. """)]
  5669. [InlineData ("01234", 3, 3, TextDirection.TopBottom_LeftRight, 1, 3, """
  5670. 0
  5671. 1
  5672. 2
  5673. """)]
  5674. public void FormatAndGetSize_WordWrap_False_Returns_Correct_Size (string text, int width, int height, TextDirection direction, int expectedWidth, int expectedHeight, string expectedDraw)
  5675. {
  5676. TextFormatter tf = new ()
  5677. {
  5678. Direction = direction,
  5679. Size = new (width, height),
  5680. Text = text,
  5681. WordWrap = false
  5682. };
  5683. Assert.False (tf.WordWrap);
  5684. Size size = tf.FormatAndGetSize ();
  5685. Assert.Equal (new (expectedWidth, expectedHeight), size);
  5686. tf.Draw (new (0, 0, width, height), Attribute.Default, Attribute.Default);
  5687. TestHelpers.AssertDriverContentsWithFrameAre (expectedDraw, _output);
  5688. }
  5689. #endregion
  5690. }