TextFormatterTests.cs 196 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219
  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. // Test that changing TextFormatter does not impact View dimensions if Dim.Auto is not in play
  5595. [Fact]
  5596. public void Not_Used_TextFormatter_Does_Not_Change_View_Size ()
  5597. {
  5598. View view = new ()
  5599. {
  5600. Text = "_1234"
  5601. };
  5602. Assert.False (view.TextFormatter.AutoSize);
  5603. Assert.Equal (Size.Empty, view.Frame.Size);
  5604. view.TextFormatter.Text = "ABC";
  5605. Assert.False (view.TextFormatter.AutoSize);
  5606. Assert.Equal (Size.Empty, view.Frame.Size);
  5607. view.TextFormatter.Alignment = Alignment.Fill;
  5608. Assert.False (view.TextFormatter.AutoSize);
  5609. Assert.Equal (Size.Empty, view.Frame.Size);
  5610. view.TextFormatter.VerticalAlignment = Alignment.Center;
  5611. Assert.False (view.TextFormatter.AutoSize);
  5612. Assert.Equal (Size.Empty, view.Frame.Size);
  5613. view.TextFormatter.HotKeySpecifier = (Rune)'*';
  5614. Assert.False (view.TextFormatter.AutoSize);
  5615. Assert.Equal (Size.Empty, view.Frame.Size);
  5616. view.TextFormatter.Text = "*ABC";
  5617. Assert.False (view.TextFormatter.AutoSize);
  5618. Assert.Equal (Size.Empty, view.Frame.Size);
  5619. }
  5620. [Fact]
  5621. public void Not_Used_TextSettings_Do_Not_Change_View_Size ()
  5622. {
  5623. View view = new ()
  5624. {
  5625. Text = "_1234"
  5626. };
  5627. Assert.False (view.TextFormatter.AutoSize);
  5628. Assert.Equal (Size.Empty, view.Frame.Size);
  5629. view.TextAlignment = Alignment.Fill;
  5630. Assert.False (view.TextFormatter.AutoSize);
  5631. Assert.Equal (Size.Empty, view.Frame.Size);
  5632. view.VerticalTextAlignment = Alignment.Center;
  5633. Assert.False (view.TextFormatter.AutoSize);
  5634. Assert.Equal (Size.Empty, view.Frame.Size);
  5635. view.HotKeySpecifier = (Rune)'*';
  5636. Assert.False (view.TextFormatter.AutoSize);
  5637. Assert.Equal (Size.Empty, view.Frame.Size);
  5638. view.Text = "*ABC";
  5639. Assert.False (view.TextFormatter.AutoSize);
  5640. Assert.Equal (Size.Empty, view.Frame.Size);
  5641. }
  5642. #region FormatAndGetSizeTests
  5643. // TODO: Add multi-line examples
  5644. // TODO: Add other TextDirection examples
  5645. [Theory]
  5646. [SetupFakeDriver]
  5647. [InlineData ("界1234", 10, 10, TextDirection.LeftRight_TopBottom, 6, 1, @"界1234")]
  5648. [InlineData ("01234", 10, 10, TextDirection.LeftRight_TopBottom, 5, 1, @"01234")]
  5649. [InlineData ("界1234", 10, 10, TextDirection.TopBottom_LeftRight, 2, 5, """
  5650. 1
  5651. 2
  5652. 3
  5653. 4
  5654. """)]
  5655. [InlineData ("01234", 10, 10, TextDirection.TopBottom_LeftRight, 1, 5, """
  5656. 0
  5657. 1
  5658. 2
  5659. 3
  5660. 4
  5661. """)]
  5662. [InlineData ("界1234", 3, 3, TextDirection.LeftRight_TopBottom, 3, 2, """
  5663. 界1
  5664. 234
  5665. """)]
  5666. [InlineData ("01234", 3, 3, TextDirection.LeftRight_TopBottom, 3, 2, """
  5667. 012
  5668. 34
  5669. """)]
  5670. [InlineData ("界1234", 3, 3, TextDirection.TopBottom_LeftRight, 3, 3, """
  5671. 界3
  5672. 1 4
  5673. 2
  5674. """)]
  5675. [InlineData ("01234", 3, 3, TextDirection.TopBottom_LeftRight, 2, 3, """
  5676. 03
  5677. 14
  5678. 2
  5679. """)]
  5680. public void FormatAndGetSize_Returns_Correct_Size (string text, int width, int height, TextDirection direction, int expectedWidth, int expectedHeight, string expectedDraw)
  5681. {
  5682. TextFormatter tf = new ()
  5683. {
  5684. Direction = direction,
  5685. Size = new (width, height),
  5686. Text = text
  5687. };
  5688. Assert.True (tf.WordWrap);
  5689. Size size = tf.FormatAndGetSize ();
  5690. Assert.Equal (new (expectedWidth, expectedHeight), size);
  5691. tf.Draw (new (0, 0, width, height), Attribute.Default, Attribute.Default);
  5692. TestHelpers.AssertDriverContentsWithFrameAre (expectedDraw, _output);
  5693. }
  5694. [Theory]
  5695. [SetupFakeDriver]
  5696. [InlineData ("界1234", 10, 10, TextDirection.LeftRight_TopBottom, 6, 1, @"界1234")]
  5697. [InlineData ("01234", 10, 10, TextDirection.LeftRight_TopBottom, 5, 1, @"01234")]
  5698. [InlineData ("界1234", 10, 10, TextDirection.TopBottom_LeftRight, 2, 5, """
  5699. 1
  5700. 2
  5701. 3
  5702. 4
  5703. """)]
  5704. [InlineData ("01234", 10, 10, TextDirection.TopBottom_LeftRight, 1, 5, """
  5705. 0
  5706. 1
  5707. 2
  5708. 3
  5709. 4
  5710. """)]
  5711. [InlineData ("界1234", 3, 3, TextDirection.LeftRight_TopBottom, 3, 1, @"界1")]
  5712. [InlineData ("01234", 3, 3, TextDirection.LeftRight_TopBottom, 3, 1, @"012")]
  5713. [InlineData ("界1234", 3, 3, TextDirection.TopBottom_LeftRight, 2, 3, """
  5714. 1
  5715. 2
  5716. """)]
  5717. [InlineData ("01234", 3, 3, TextDirection.TopBottom_LeftRight, 1, 3, """
  5718. 0
  5719. 1
  5720. 2
  5721. """)]
  5722. public void FormatAndGetSize_WordWrap_False_Returns_Correct_Size (string text, int width, int height, TextDirection direction, int expectedWidth, int expectedHeight, string expectedDraw)
  5723. {
  5724. TextFormatter tf = new ()
  5725. {
  5726. Direction = direction,
  5727. Size = new (width, height),
  5728. Text = text,
  5729. WordWrap = false
  5730. };
  5731. Assert.False (tf.WordWrap);
  5732. Size size = tf.FormatAndGetSize ();
  5733. Assert.Equal (new (expectedWidth, expectedHeight), size);
  5734. tf.Draw (new (0, 0, width, height), Attribute.Default, Attribute.Default);
  5735. TestHelpers.AssertDriverContentsWithFrameAre (expectedDraw, _output);
  5736. }
  5737. #endregion
  5738. }