CustomScpExplorer.cpp 220 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012
  1. //---------------------------------------------------------------------------
  2. #define NO_WIN32_LEAN_AND_MEAN
  3. #include <vcl.h>
  4. #pragma hdrstop
  5. #include <Common.h>
  6. #include "CustomScpExplorer.h"
  7. #include <Bookmarks.h>
  8. #include <Interface.h>
  9. #include <Exceptions.h>
  10. #include <CoreMain.h>
  11. #include <FileSystems.h>
  12. #include <TextsCore.h>
  13. #include <TextsWin.h>
  14. #include <HelpWin.h>
  15. #include <VCLCommon.h>
  16. #include <Log.h>
  17. #include <Progress.h>
  18. #include <SynchronizeProgress.h>
  19. #include <DragExt.h>
  20. #include <WinApi.h>
  21. #include "GUITools.h"
  22. #include "NonVisual.h"
  23. #include "Glyphs.h"
  24. #include "Tools.h"
  25. #include "WinConfiguration.h"
  26. #include "TerminalManager.h"
  27. #include "EditorManager.h"
  28. #include "Setup.h"
  29. #include <Consts.hpp>
  30. #include <DateUtils.hpp>
  31. //---------------------------------------------------------------------------
  32. #pragma package(smart_init)
  33. #pragma link "CustomDirView"
  34. #pragma link "CustomUnixDirView"
  35. #pragma link "IEListView"
  36. #pragma link "NortonLikeListView"
  37. #pragma link "UnixDirView"
  38. #pragma link "CustomDriveView"
  39. #pragma link "UnixDriveView"
  40. #pragma link "CustomDriveView"
  41. #pragma link "TB2Dock"
  42. #pragma link "TBXStatusBars"
  43. #pragma link "TB2Item"
  44. #pragma link "TB2Toolbar"
  45. #ifndef NO_RESOURCES
  46. #pragma resource "*.dfm"
  47. #endif
  48. //---------------------------------------------------------------------------
  49. #define SAVE_SELECTION(DIRVIEW) \
  50. UnicodeString FocusFile = L""; \
  51. UnicodeString LastFocusedFile = L""; \
  52. if (DIRVIEW->ItemFocused) LastFocusedFile = DIRVIEW->ItemFocused->Caption; \
  53. { TListItem * ClosestUnselected = DIRVIEW->ClosestUnselected(DIRVIEW->ItemFocused); \
  54. if (ClosestUnselected) FocusFile = ClosestUnselected->Caption; }
  55. #define RESTORE_SELECTION(DIRVIEW) \
  56. if (!LastFocusedFile.IsEmpty() && \
  57. (!DIRVIEW->ItemFocused || (DIRVIEW->ItemFocused->Caption != LastFocusedFile))) \
  58. { \
  59. TListItem *ItemToSelect = DIRVIEW->FindFileItem(FocusFile); \
  60. if (ItemToSelect) \
  61. { \
  62. DIRVIEW->ItemFocused = ItemToSelect; \
  63. DIRVIEW->ItemFocused->MakeVisible(False); \
  64. } \
  65. }
  66. //---------------------------------------------------------------------------
  67. #define WM_COMPONENT_HIDE (WM_WINSCP_USER + 4)
  68. //---------------------------------------------------------------------------
  69. class TMutexGuard
  70. {
  71. public:
  72. TMutexGuard(HANDLE AMutex, int Message = MUTEX_RELEASE_TIMEOUT,
  73. int Timeout = 5000)
  74. {
  75. FMutex = NULL;
  76. unsigned long WaitResult = WaitForSingleObject(AMutex, Timeout);
  77. if (WaitResult == WAIT_TIMEOUT)
  78. {
  79. throw Exception(LoadStr(MUTEX_RELEASE_TIMEOUT));
  80. }
  81. else
  82. {
  83. FMutex = AMutex;
  84. }
  85. }
  86. ~TMutexGuard()
  87. {
  88. if (FMutex != NULL)
  89. {
  90. ReleaseMutex(FMutex);
  91. }
  92. }
  93. private:
  94. HANDLE FMutex;
  95. };
  96. //---------------------------------------------------------------------------
  97. struct TTransferOperationParam
  98. {
  99. TTransferOperationParam();
  100. UnicodeString TargetDirectory;
  101. bool Temp;
  102. bool DragDrop;
  103. };
  104. //---------------------------------------------------------------------------
  105. TTransferOperationParam::TTransferOperationParam()
  106. {
  107. Temp = false;
  108. DragDrop = false;
  109. }
  110. //---------------------------------------------------------------------------
  111. class TTransferPresetNoteData : public TObject
  112. {
  113. public:
  114. UnicodeString Message;
  115. TStrings * More;
  116. virtual __fastcall ~TTransferPresetNoteData()
  117. {
  118. delete More;
  119. }
  120. };
  121. //---------------------------------------------------------------------------
  122. __fastcall TCustomScpExplorerForm::TCustomScpExplorerForm(TComponent* Owner):
  123. FFormRestored(false),
  124. TForm(Owner),
  125. FDirViewMatchMask(-1, true)
  126. {
  127. FCurrentSide = osRemote;
  128. FDocks = new TList();
  129. RestoreParams();
  130. ConfigurationChanged();
  131. RemoteDirView->Invalidate();
  132. assert(NonVisualDataModule && !NonVisualDataModule->ScpExplorer);
  133. NonVisualDataModule->ScpExplorer = this;
  134. Application->OnMinimize = ApplicationMinimize;
  135. Application->OnRestore = ApplicationRestore;
  136. FAutoOperation = false;
  137. FForceExecution = false;
  138. FShowStatusBarHint = false;
  139. FIgnoreNextSysCommand = false;
  140. FErrorList = NULL;
  141. FSynchronizeProgressForm = NULL;
  142. FProgressForm = NULL;
  143. FRefreshLocalDirectory = false;
  144. FRefreshRemoteDirectory = false;
  145. FDDMoveSlipped = false;
  146. FDDExtMapFile = NULL;
  147. // CreateMutexW keeps failing with ERROR_NOACCESS
  148. FDDExtMutex = CreateMutexA(NULL, false, AnsiString(DRAG_EXT_MUTEX).c_str());
  149. assert(FDDExtMutex != NULL);
  150. FDDTargetControl = NULL;
  151. FDelayedDeletionTimer = NULL;
  152. FDelayedDeletionList = new TStringList();
  153. FDDFileList = NULL;
  154. FPendingTempSpaceWarn = false;
  155. FCapturedLog = NULL;
  156. FDragDropOperation = false;
  157. memset(&FHistoryMenu, 0, sizeof(FHistoryMenu));
  158. FAllowTransferPresetAutoSelect = true;
  159. FCopyParamDefault = L"";
  160. FSynchronizeController = NULL;
  161. FPendingQueueActionItem = NULL;
  162. FLockLevel = 0;
  163. FAlternativeDelete = false;
  164. FTrayIcon = new ::TTrayIcon(0);
  165. FTrayIcon->OnClick = TrayIconClick;
  166. FMaxQueueLength = 0;
  167. FEditorManager = new TEditorManager();
  168. FEditorManager->OnFileChange = ExecutedFileChanged;
  169. FEditorManager->OnFileReload = ExecutedFileReload;
  170. FEditorManager->OnFileEarlyClosed = ExecutedFileEarlyClosed;
  171. FLocalEditors = new TList();
  172. FQueueStatus = NULL;
  173. FQueueStatusSection = new TCriticalSection();
  174. FQueueStatusInvalidated = false;
  175. FQueueItemInvalidated = false;
  176. FQueueActedItem = NULL;
  177. FQueueController = new TQueueController(QueueView2);
  178. FUserActionTimer = new TTimer(this);
  179. FUserActionTimer->Enabled = false;
  180. FUserActionTimer->Interval = 10;
  181. FUserActionTimer->OnTimer = UserActionTimer;
  182. FNotes = new TStringList();
  183. FNoteTimer = new TTimer(this);
  184. FNoteTimer->Enabled = false;
  185. FNoteTimer->OnTimer = NoteTimer;
  186. FOnNoteClick = NULL;
  187. FOle32Library = LoadLibrary(L"Ole32.dll");
  188. FDragMoveCursor = FOle32Library != NULL ?
  189. LoadCursor(FOle32Library, MAKEINTRESOURCE(2)) : NULL;
  190. UseSystemSettings(this);
  191. TTBXStringList * TransferList = dynamic_cast<TTBXStringList*>(
  192. static_cast<TObject*>(GetComponent(fcTransferList)));
  193. assert(TransferList != NULL);
  194. FTransferListHoverIndex = -1;
  195. TransferList->OnChange = TransferListChange;
  196. TransferList->OnDrawItem = TransferListDrawItem;
  197. class TTBXPublicItem : public TTBXCustomItem
  198. {
  199. public:
  200. __property ItemStyle;
  201. };
  202. TTBXPublicItem * ColorMenu;
  203. ColorMenu =
  204. reinterpret_cast<TTBXPublicItem *>(
  205. dynamic_cast<TTBXCustomItem *>(
  206. static_cast<TObject *>(GetComponent(fcColorMenu))));
  207. assert(ColorMenu != NULL);
  208. ColorMenu->ItemStyle = ColorMenu->ItemStyle << tbisSubmenu;
  209. ColorMenu =
  210. reinterpret_cast<TTBXPublicItem *>(
  211. dynamic_cast<TTBXCustomItem *>(
  212. static_cast<TObject *>(NonVisualDataModule->ColorMenuItem)));
  213. assert(ColorMenu != NULL);
  214. ColorMenu->ItemStyle = ColorMenu->ItemStyle << tbisSubmenu;
  215. TTBXColorPalette * ColorPalette =
  216. dynamic_cast<TTBXColorPalette *>(
  217. static_cast<TObject *>(GetComponent(fcColorPalette)));
  218. assert(ColorPalette != NULL);
  219. ColorPalette->OnChange = NonVisualDataModule->SessionColorPaletteChange;
  220. RemoteDirView->Font = Screen->IconFont;
  221. reinterpret_cast<TLabel*>(QueueSplitter)->OnDblClick = QueueSplitterDblClick;
  222. FSystemImageList = SharedSystemImageList(false);
  223. FSystemImageList->DrawingStyle = dsTransparent;
  224. FCustomCommandMenu = CreateTBXPopupMenu(this);
  225. FCustomCommandLocalFileList = NULL;
  226. FCustomCommandRemoteFileList = NULL;
  227. FSessionColors = new TImageList(this);
  228. FSessionColors->SetSize(10, 10);
  229. SessionsPageControl->Images = FSessionColors;
  230. StartUpdates();
  231. }
  232. //---------------------------------------------------------------------------
  233. __fastcall TCustomScpExplorerForm::~TCustomScpExplorerForm()
  234. {
  235. // this has to be one of the very first things to do
  236. StopUpdateThread();
  237. SessionsPageControl->Images = NULL;
  238. SAFE_DESTROY(FSessionColors);
  239. SAFE_DESTROY(FSessionsDragDropFilesEx);
  240. delete FCustomCommandLocalFileList;
  241. delete FCustomCommandRemoteFileList;
  242. delete FCustomCommandMenu;
  243. delete FSystemImageList;
  244. FSystemImageList = NULL;
  245. if (Application->OnHint == ApplicationHint)
  246. {
  247. Application->OnHint = NULL;
  248. }
  249. assert(Application->OnMinimize == ApplicationMinimize);
  250. Application->OnMinimize = NULL;
  251. assert(Application->OnRestore == ApplicationRestore);
  252. Application->OnRestore = NULL;
  253. delete FTrayIcon;
  254. FTrayIcon = NULL;
  255. FEditorManager->CloseInternalEditors(ForceCloseInternalEditor);
  256. delete FEditorManager;
  257. ForceCloseLocalEditors();
  258. delete FLocalEditors;
  259. if (FDelayedDeletionTimer)
  260. {
  261. DoDelayedDeletion(NULL);
  262. SAFE_DESTROY(FDelayedDeletionTimer);
  263. }
  264. SAFE_DESTROY(FDelayedDeletionList);
  265. // sometimes we do not get DDEnd so the list is not released
  266. SAFE_DESTROY(FDDFileList);
  267. assert(FSynchronizeController == NULL);
  268. CloseHandle(FDDExtMutex);
  269. FDDExtMutex = NULL;
  270. FreeLibrary(FOle32Library);
  271. FOle32Library = NULL;
  272. FDragMoveCursor = NULL;
  273. assert(!FErrorList);
  274. StoreParams();
  275. Terminal = NULL;
  276. Queue = NULL;
  277. assert(NonVisualDataModule && (NonVisualDataModule->ScpExplorer == this));
  278. NonVisualDataModule->ScpExplorer = NULL;
  279. delete FQueueController;
  280. FQueueController = NULL;
  281. delete FQueueStatusSection;
  282. FQueueStatusSection = NULL;
  283. delete FQueueStatus;
  284. FQueueStatus = NULL;
  285. delete FUserActionTimer;
  286. FUserActionTimer = NULL;
  287. delete FNoteTimer;
  288. delete FNotes;
  289. delete FNoteData;
  290. SAFE_DESTROY(FDocks);
  291. SAFE_DESTROY(FHistoryMenu[0][0]);
  292. SAFE_DESTROY(FHistoryMenu[0][1]);
  293. SAFE_DESTROY(FHistoryMenu[1][0]);
  294. SAFE_DESTROY(FHistoryMenu[1][1]);
  295. }
  296. //---------------------------------------------------------------------------
  297. void __fastcall TCustomScpExplorerForm::SetTerminal(TTerminal * value)
  298. {
  299. if (FTerminal != value)
  300. {
  301. TerminalChanging();
  302. FTerminal = value;
  303. bool PrevAllowTransferPresetAutoSelect = FAllowTransferPresetAutoSelect;
  304. FAllowTransferPresetAutoSelect = false;
  305. try
  306. {
  307. TerminalChanged();
  308. }
  309. __finally
  310. {
  311. FAllowTransferPresetAutoSelect = PrevAllowTransferPresetAutoSelect;
  312. }
  313. if (Terminal != NULL)
  314. {
  315. TransferPresetAutoSelect();
  316. }
  317. }
  318. }
  319. //---------------------------------------------------------------------------
  320. void __fastcall TCustomScpExplorerForm::TerminalChanging()
  321. {
  322. if (FTerminal != NULL)
  323. {
  324. UpdateTerminal(Terminal);
  325. }
  326. }
  327. //---------------------------------------------------------------------------
  328. void __fastcall TCustomScpExplorerForm::TerminalChanged()
  329. {
  330. RemoteDirView->Terminal = Terminal;
  331. NonVisualDataModule->ResetQueueOnceEmptyOperation();
  332. if (Terminal)
  333. {
  334. if (Terminal->Active)
  335. {
  336. Terminal->RefreshDirectory();
  337. }
  338. TManagedTerminal * ManagedTerminal = dynamic_cast<TManagedTerminal *>(Terminal);
  339. assert(ManagedTerminal != NULL);
  340. if (WinConfiguration->PreservePanelState)
  341. {
  342. if (ManagedTerminal->RemoteExplorerState != NULL)
  343. {
  344. RemoteDirView->RestoreState(ManagedTerminal->RemoteExplorerState);
  345. }
  346. else
  347. {
  348. RemoteDirView->ClearState();
  349. }
  350. }
  351. SessionColor = ManagedTerminal->Color;
  352. InitStatusBar();
  353. }
  354. TerminalListChanged(NULL);
  355. UpdateTransferList();
  356. }
  357. //---------------------------------------------------------------------------
  358. void __fastcall TCustomScpExplorerForm::SetQueue(TTerminalQueue * value)
  359. {
  360. if (Queue != value)
  361. {
  362. if (FQueue != NULL)
  363. {
  364. FQueue->OnListUpdate = NULL;
  365. FQueue->OnQueueItemUpdate = NULL;
  366. }
  367. FQueue = value;
  368. if (FQueue != NULL)
  369. {
  370. assert(FQueue->OnListUpdate == NULL);
  371. FQueue->OnListUpdate = QueueListUpdate;
  372. assert(FQueue->OnQueueItemUpdate == NULL);
  373. FQueue->OnQueueItemUpdate = QueueItemUpdate;
  374. }
  375. QueueChanged();
  376. }
  377. }
  378. //---------------------------------------------------------------------------
  379. void __fastcall TCustomScpExplorerForm::QueueView2Deletion(TObject * /*Sender*/,
  380. TListItem * Item)
  381. {
  382. if (FQueueActedItem == Item)
  383. {
  384. FQueueActedItem = NULL;
  385. if ((QueueView2->PopupMenu != NULL) &&
  386. (QueueView2->PopupMenu->PopupComponent == QueueView2))
  387. {
  388. // rather "trick", suggested by Jordan on jrsoftware.toolbar2000
  389. ReleaseCapture();
  390. }
  391. }
  392. if (Item->Data == FPendingQueueActionItem)
  393. {
  394. FPendingQueueActionItem = NULL;
  395. }
  396. }
  397. //---------------------------------------------------------------------------
  398. void __fastcall TCustomScpExplorerForm::UpdateQueueStatus(bool AppIdle, bool QueueChanging)
  399. {
  400. {
  401. TGuard Guard(FQueueStatusSection);
  402. FQueueStatusInvalidated = false;
  403. if (FQueue != NULL)
  404. {
  405. FQueueStatus = FQueue->CreateStatus(FQueueStatus);
  406. }
  407. }
  408. if ((FQueueStatus != NULL) && (FQueueStatus->Count > FMaxQueueLength))
  409. {
  410. FMaxQueueLength = FQueueStatus->Count;
  411. Configuration->Usage->SetMax(L"MaxQueueLength", FMaxQueueLength);
  412. }
  413. FQueueController->UpdateQueueStatus(FQueueStatus);
  414. UpdateQueueView();
  415. bool IsEmpty = (FQueueStatus == NULL) || (FQueueStatus->Count == 0);
  416. if (IsEmpty && (Terminal != NULL))
  417. {
  418. TOnceDoneOperation OnceDoneOperation =
  419. NonVisualDataModule->CurrentQueueOnceEmptyOperation();
  420. NonVisualDataModule->ResetQueueOnceEmptyOperation();
  421. if ((FQueue != NULL) && !WinConfiguration->EnableQueueByDefault && !QueueChanging)
  422. {
  423. FQueue->Enabled = false;
  424. }
  425. if ((OnceDoneOperation != odoIdle) && AppIdle)
  426. {
  427. Terminal->CloseOnCompletion(OnceDoneOperation, LoadStr(CLOSED_ON_QUEUE_EMPTY));
  428. }
  429. }
  430. }
  431. //---------------------------------------------------------------------------
  432. void __fastcall TCustomScpExplorerForm::UpdateQueueView()
  433. {
  434. ComponentVisible[fcQueueView] =
  435. (WinConfiguration->QueueView.Show == qvShow) ||
  436. ((WinConfiguration->QueueView.Show == qvHideWhenEmpty) &&
  437. (FQueueStatus != NULL) && (FQueueStatus->Count > 0));
  438. }
  439. //---------------------------------------------------------------------------
  440. void __fastcall TCustomScpExplorerForm::QueueChanged()
  441. {
  442. if (FQueueStatus != NULL)
  443. {
  444. delete FQueueStatus;
  445. FQueueStatus = NULL;
  446. }
  447. UpdateQueueStatus(false, true);
  448. }
  449. //---------------------------------------------------------------------------
  450. void __fastcall TCustomScpExplorerForm::QueueListUpdate(TTerminalQueue * Queue)
  451. {
  452. if (FQueue == Queue)
  453. {
  454. FQueueStatusInvalidated = true;
  455. }
  456. }
  457. //---------------------------------------------------------------------------
  458. void __fastcall TCustomScpExplorerForm::QueueItemUpdate(TTerminalQueue * Queue,
  459. TQueueItem * Item)
  460. {
  461. if (FQueue == Queue)
  462. {
  463. TGuard Guard(FQueueStatusSection);
  464. // this may be running in parallel with QueueChanged
  465. if (FQueueStatus != NULL)
  466. {
  467. TQueueItemProxy * QueueItem = FQueueStatus->FindByQueueItem(Item);
  468. if ((Item->Status == TQueueItem::qsDone) && (Terminal != NULL))
  469. {
  470. FRefreshLocalDirectory = (QueueItem == NULL) ||
  471. (!QueueItem->Info->ModifiedLocal.IsEmpty());
  472. FRefreshRemoteDirectory = (QueueItem == NULL) ||
  473. (!QueueItem->Info->ModifiedRemote.IsEmpty());
  474. }
  475. if (QueueItem != NULL)
  476. {
  477. QueueItem->UserData = (void*)true;
  478. FQueueItemInvalidated = true;
  479. }
  480. }
  481. }
  482. }
  483. //---------------------------------------------------------------------------
  484. void __fastcall TCustomScpExplorerForm::RefreshQueueItems(bool AppIdle)
  485. {
  486. if (FQueueStatus != NULL)
  487. {
  488. bool QueueAutoPopup = GUIConfiguration->QueueAutoPopup;
  489. bool Refresh = FQueueItemInvalidated;
  490. FQueueItemInvalidated = false;
  491. int Limit = Refresh ? FQueueStatus->Count : FQueueStatus->ActiveCount;
  492. bool Updated = false;
  493. bool Update;
  494. TQueueItemProxy * QueueItem;
  495. bool WasUserAction;
  496. for (int Index = 0; Index < Limit; Index++)
  497. {
  498. Update = false;
  499. QueueItem = FQueueStatus->Items[Index];
  500. WasUserAction = TQueueItem::IsUserActionStatus(QueueItem->Status);
  501. if (AppIdle && QueueAutoPopup && WasUserAction &&
  502. (FPendingQueueActionItem == NULL))
  503. {
  504. FPendingQueueActionItem = QueueItem;
  505. FUserActionTimer->Enabled = true;
  506. }
  507. if ((bool)QueueItem->UserData)
  508. {
  509. QueueItem->UserData = (void*)false;
  510. QueueItem->Update();
  511. Updated = true;
  512. Update = true;
  513. }
  514. else if (FQueueController->QueueItemNeedsFrequentRefresh(QueueItem))
  515. {
  516. Update = true;
  517. }
  518. if (Update)
  519. {
  520. FQueueController->RefreshQueueItem(QueueItem);
  521. }
  522. }
  523. if (Updated)
  524. {
  525. NonVisualDataModule->UpdateNonVisibleActions();
  526. }
  527. }
  528. }
  529. //---------------------------------------------------------------------------
  530. void __fastcall TCustomScpExplorerForm::UpdateTransferList()
  531. {
  532. TTBXStringList * TransferList = dynamic_cast<TTBXStringList*>(
  533. static_cast<TComponent*>(GetComponent(fcTransferList)));
  534. TTBXDropDownItem * TransferDropDown = dynamic_cast<TTBXDropDownItem*>(
  535. static_cast<TComponent*>(GetComponent(fcTransferDropDown)));
  536. TransferList->Strings->BeginUpdate();
  537. try
  538. {
  539. TransferList->Strings->Assign(GUIConfiguration->CopyParamList->NameList);
  540. TransferList->Strings->Insert(0, StripHotkey(LoadStr(COPY_PARAM_DEFAULT)));
  541. TransferList->ItemIndex = GUIConfiguration->CopyParamIndex + 1;
  542. if (FTransferDropDownHint.IsEmpty())
  543. {
  544. FTransferDropDownHint = TransferDropDown->Hint;
  545. }
  546. // this way we get name for "default" settings (COPY_PARAM_DEFAULT)
  547. UnicodeString Name = TransferList->Strings->Strings[TransferList->ItemIndex];
  548. TransferDropDown->Text = StripHotkey(Name);
  549. TransferDropDown->Hint = FORMAT(L"%s\n \n%s:\n%s|%s",
  550. (FTransferDropDownHint, StripHotkey(Name),
  551. GUIConfiguration->CurrentCopyParam.GetInfoStr(L"; ",
  552. FLAGMASK(Terminal != NULL, Terminal->UsableCopyParamAttrs(0).General)),
  553. FTransferDropDownHint));
  554. // update the label, otherwise when it is updated only on the first draw
  555. // of the list, it is drawn "bold" for some reason
  556. FTransferListHoverIndex = TransferList->ItemIndex;
  557. UpdateTransferLabel();
  558. }
  559. __finally
  560. {
  561. TransferList->Strings->EndUpdate();
  562. }
  563. }
  564. //---------------------------------------------------------------------------
  565. void __fastcall TCustomScpExplorerForm::UpdateCustomCommandsToolbar()
  566. {
  567. TTBXToolbar * Toolbar = dynamic_cast<TTBXToolbar *>(GetComponent(fcCustomCommandsBand));
  568. assert(Toolbar != NULL);
  569. NonVisualDataModule->UpdateCustomCommandsToolbar(Toolbar);
  570. }
  571. //---------------------------------------------------------------------------
  572. void __fastcall TCustomScpExplorerForm::UpdateActions()
  573. {
  574. TForm::UpdateActions();
  575. if (ComponentVisible[fcCustomCommandsBand])
  576. {
  577. UpdateCustomCommandsToolbar();
  578. }
  579. }
  580. //---------------------------------------------------------------------------
  581. void __fastcall TCustomScpExplorerForm::ConfigurationChanged()
  582. {
  583. assert(Configuration && RemoteDirView);
  584. RemoteDirView->DDAllowMove = WinConfiguration->DDAllowMoveInit;
  585. RemoteDirView->DimmHiddenFiles = WinConfiguration->DimmHiddenFiles;
  586. RemoteDirView->ShowHiddenFiles = WinConfiguration->ShowHiddenFiles;
  587. RemoteDirView->FormatSizeBytes = WinConfiguration->FormatSizeBytes;
  588. RemoteDirView->ShowInaccesibleDirectories = WinConfiguration->ShowInaccesibleDirectories;
  589. if (RemoteDirView->RowSelect != WinConfiguration->FullRowSelect)
  590. {
  591. RemoteDirView->RowSelect = WinConfiguration->FullRowSelect;
  592. // selection is not redrawn automatically when RowSelect changes
  593. RemoteDirView->Invalidate();
  594. }
  595. RemoteDriveView->DDAllowMove = WinConfiguration->DDAllowMoveInit;
  596. RemoteDriveView->DimmHiddenDirs = WinConfiguration->DimmHiddenFiles;
  597. RemoteDriveView->ShowHiddenDirs = WinConfiguration->ShowHiddenFiles;
  598. RemoteDriveView->ShowInaccesibleDirectories = WinConfiguration->ShowInaccesibleDirectories;
  599. SetDockAllowDrag(!WinConfiguration->LockToolbars);
  600. UpdateTransferList();
  601. if (Terminal != NULL)
  602. {
  603. TransferPresetAutoSelect();
  604. }
  605. UpdateQueueView();
  606. UpdateControls();
  607. // this can be called even before constuctor finishes.
  608. if (FEditorManager != NULL)
  609. {
  610. FEditorManager->ProcessFiles(FileConfigurationChanged, NULL);
  611. }
  612. // this can be called even before constuctor finishes.
  613. if (FLocalEditors != NULL)
  614. {
  615. for (int Index = 0; Index < FLocalEditors->Count; Index++)
  616. {
  617. ReconfigureEditorForm(static_cast<TForm *>(FLocalEditors->Items[Index]));
  618. }
  619. }
  620. if (ComponentVisible[fcCustomCommandsBand])
  621. {
  622. UpdateCustomCommandsToolbar();
  623. }
  624. }
  625. //---------------------------------------------------------------------------
  626. void __fastcall TCustomScpExplorerForm::FileConfigurationChanged(
  627. const UnicodeString FileName, TEditedFileData & /*Data*/, TObject * Token,
  628. void * /*Arg*/)
  629. {
  630. if (Token != NULL)
  631. {
  632. TForm * Editor = dynamic_cast<TForm*>(Token);
  633. assert(Editor != NULL);
  634. ReconfigureEditorForm(Editor);
  635. }
  636. }
  637. //---------------------------------------------------------------------------
  638. bool __fastcall TCustomScpExplorerForm::CopyParamDialog(
  639. TTransferDirection Direction, TTransferType Type, bool Temp,
  640. TStrings * FileList, UnicodeString & TargetDirectory, TGUICopyParamType & CopyParam,
  641. bool Confirm, bool DragDrop)
  642. {
  643. bool Result = true;
  644. assert(Terminal && Terminal->Active);
  645. // Temp means d&d here so far, may change in future!
  646. if (Temp && (Direction == tdToLocal) && (Type == ttMove) &&
  647. !WinConfiguration->DDAllowMove)
  648. {
  649. TMessageParams Params(mpNeverAskAgainCheck);
  650. unsigned int Answer = MessageDialog(LoadStr(DND_DOWNLOAD_MOVE_WARNING), qtWarning,
  651. qaOK | qaCancel, HELP_DND_DOWNLOAD_MOVE_WARNING, &Params);
  652. if (Answer == qaNeverAskAgain)
  653. {
  654. WinConfiguration->DDAllowMove = true;
  655. }
  656. else if (Answer == qaCancel)
  657. {
  658. Result = false;
  659. }
  660. }
  661. // these parameters are known in advance
  662. int Params =
  663. FLAGMASK(Type == ttMove, cpDelete);
  664. bool ToTemp = (Temp && (Direction == tdToLocal));
  665. if (Result && Confirm && WinConfiguration->ConfirmTransferring)
  666. {
  667. bool DisableNewerOnly =
  668. (!Terminal->IsCapable[fcNewerOnlyUpload] && (Direction == tdToRemote)) ||
  669. ToTemp;
  670. int Options =
  671. FLAGMASK(DisableNewerOnly, coDisableNewerOnly) |
  672. FLAGMASK(ToTemp, coTemp) |
  673. coDoNotShowAgain;
  674. TUsableCopyParamAttrs UsableCopyParamAttrs = Terminal->UsableCopyParamAttrs(Params);
  675. int CopyParamAttrs = (Direction == tdToRemote ?
  676. UsableCopyParamAttrs.Upload : UsableCopyParamAttrs.Download);
  677. int OutputOptions = 0;
  678. Result = DoCopyDialog(Direction == tdToRemote, Type == ttMove,
  679. FileList, TargetDirectory, &CopyParam, Options, CopyParamAttrs, &OutputOptions);
  680. if (Result && FLAGSET(OutputOptions, cooDoNotShowAgain))
  681. {
  682. if (DragDrop)
  683. {
  684. WinConfiguration->DDTransferConfirmation = false;
  685. }
  686. else
  687. {
  688. WinConfiguration->ConfirmTransferring = false;
  689. }
  690. }
  691. }
  692. if (Result && CopyParam.Queue && !ToTemp)
  693. {
  694. Configuration->Usage->Inc(L"TransfersOnBackground");
  695. // these parameter are known only after transfer dialog
  696. Params |=
  697. (CopyParam.QueueNoConfirmation ? cpNoConfirmation : 0) |
  698. (CopyParam.NewerOnly ? cpNewerOnly : 0);
  699. if (CopyParam.QueueIndividually)
  700. {
  701. for (int Index = 0; Index < FileList->Count; Index++)
  702. {
  703. TStrings * FileList1 = new TStringList();
  704. try
  705. {
  706. FileList1->AddObject(FileList->Strings[Index], FileList->Objects[Index]);
  707. AddQueueItem(Direction, FileList1, TargetDirectory, CopyParam, Params);
  708. }
  709. __finally
  710. {
  711. delete FileList1;
  712. }
  713. }
  714. }
  715. else
  716. {
  717. AddQueueItem(Direction, FileList, TargetDirectory, CopyParam, Params);
  718. }
  719. Result = false;
  720. TOperationSide Side = ((Direction == tdToRemote) ? osLocal : osRemote);
  721. if (HasDirView[Side])
  722. {
  723. DirView(Side)->SelectAll(smNone);
  724. }
  725. }
  726. return Result;
  727. }
  728. //---------------------------------------------------------------------------
  729. void __fastcall TCustomScpExplorerForm::AddQueueItem(
  730. TTransferDirection Direction, TStrings * FileList,
  731. const UnicodeString TargetDirectory, const TCopyParamType & CopyParam,
  732. int Params)
  733. {
  734. assert(Queue != NULL);
  735. TQueueItem * QueueItem;
  736. if (Direction == tdToRemote)
  737. {
  738. QueueItem = new TUploadQueueItem(Terminal, FileList, TargetDirectory,
  739. &CopyParam, Params);
  740. }
  741. else
  742. {
  743. QueueItem = new TDownloadQueueItem(Terminal, FileList, TargetDirectory,
  744. &CopyParam, Params);
  745. }
  746. Queue->AddItem(QueueItem);
  747. }
  748. //---------------------------------------------------------------------------
  749. void __fastcall TCustomScpExplorerForm::RestoreFormParams()
  750. {
  751. }
  752. //---------------------------------------------------------------------------
  753. void __fastcall TCustomScpExplorerForm::RestoreParams()
  754. {
  755. assert(FDocks != NULL);
  756. for (int Index = 0; Index < ComponentCount; Index++)
  757. {
  758. TTBDock * Dock = dynamic_cast<TTBDock *>(Components[Index]);
  759. if ((Dock != NULL) && (Dock->Tag == 0))
  760. {
  761. FDocks->Add(Dock);
  762. }
  763. }
  764. // IDE often looses this link
  765. RemoteDirView->HeaderImages = GlyphsModule->ArrowImages;
  766. ConfigurationChanged();
  767. QueuePanel->Height = WinConfiguration->QueueView.Height;
  768. LoadListViewStr(QueueView2, WinConfiguration->QueueView.Layout);
  769. QueueDock->Visible = WinConfiguration->QueueView.ToolBar;
  770. }
  771. //---------------------------------------------------------------------------
  772. void __fastcall TCustomScpExplorerForm::StoreParams()
  773. {
  774. WinConfiguration->QueueView.Height = QueuePanel->Height;
  775. WinConfiguration->QueueView.Layout = GetListViewStr(QueueView2);
  776. WinConfiguration->QueueView.ToolBar = QueueDock->Visible;
  777. }
  778. //---------------------------------------------------------------------------
  779. void __fastcall TCustomScpExplorerForm::CreateParams(TCreateParams & Params)
  780. {
  781. if (!FFormRestored)
  782. {
  783. FFormRestored = true;
  784. RestoreFormParams();
  785. }
  786. TForm::CreateParams(Params);
  787. }
  788. //---------------------------------------------------------------------------
  789. void __fastcall TCustomScpExplorerForm::SetDockAllowDrag(bool value)
  790. {
  791. assert(FDocks != NULL);
  792. for (int Index = 0; Index < FDocks->Count; Index++)
  793. {
  794. static_cast<TTBDock*>(FDocks->Items[Index])->AllowDrag = value;
  795. }
  796. }
  797. //---------------------------------------------------------------------------
  798. void __fastcall TCustomScpExplorerForm::LoadToolbarsLayoutStr(UnicodeString LayoutStr)
  799. {
  800. SetDockAllowDrag(true);
  801. ::LoadToolbarsLayoutStr(this, LayoutStr);
  802. SetDockAllowDrag(!WinConfiguration->LockToolbars);
  803. }
  804. //---------------------------------------------------------------------------
  805. UnicodeString __fastcall TCustomScpExplorerForm::GetToolbarsLayoutStr()
  806. {
  807. UnicodeString Result;
  808. SetDockAllowDrag(true);
  809. Result = ::GetToolbarsLayoutStr(this);
  810. SetDockAllowDrag(!WinConfiguration->LockToolbars);
  811. return Result;
  812. }
  813. //---------------------------------------------------------------------------
  814. void __fastcall TCustomScpExplorerForm::FileOperationProgress(
  815. TFileOperationProgressType & ProgressData, TCancelStatus & /*Cancel*/)
  816. {
  817. // Download to temporary local directory
  818. if (FPendingTempSpaceWarn && ProgressData.InProgress && ProgressData.TotalSizeSet)
  819. {
  820. bool Continue = true;
  821. FPendingTempSpaceWarn = false;
  822. DoWarnLackOfTempSpace(ProgressData.Directory, ProgressData.TotalSize, Continue);
  823. if (!Continue)
  824. {
  825. Abort();
  826. }
  827. }
  828. // operation is being executed and we still didn't show up progress form
  829. if (ProgressData.InProgress && !FProgressForm)
  830. {
  831. FProgressForm = new TProgressForm(Application);
  832. FProgressForm->DeleteToRecycleBin = (ProgressData.Side == osLocal ?
  833. (WinConfiguration->DeleteToRecycleBin != FAlternativeDelete) :
  834. ((Terminal->SessionData->DeleteToRecycleBin != FAlternativeDelete) &&
  835. !Terminal->SessionData->RecycleBinPath.IsEmpty()));
  836. // When main window is hidden, synchronisation form does not exist,
  837. // we suppose "/upload" or URL download mode
  838. if (!Visible && (ProgressData.Operation != foCalculateSize) &&
  839. (ProgressData.Operation != foCalculateChecksum) &&
  840. (FSynchronizeProgressForm == NULL))
  841. {
  842. FProgressForm->OnceDoneOperation = odoDisconnect;
  843. }
  844. if (FTaskbarList != NULL)
  845. {
  846. FTaskbarList->SetProgressState(Handle, TBPF_NORMAL);
  847. }
  848. }
  849. // operation is finished (or terminated), so we hide progress form
  850. else if (!ProgressData.InProgress && FProgressForm)
  851. {
  852. if (FTaskbarList != NULL)
  853. {
  854. FTaskbarList->SetProgressState(Handle, TBPF_NOPROGRESS);
  855. }
  856. SAFE_DESTROY(FProgressForm);
  857. if ((ProgressData.Operation != foCalculateSize) &&
  858. (ProgressData.Cancel == csContinue) &&
  859. !FAutoOperation)
  860. {
  861. OperationComplete(ProgressData.StartTime);
  862. }
  863. }
  864. if (FProgressForm)
  865. {
  866. FProgressForm->SetProgressData(ProgressData);
  867. if (FTaskbarList != NULL)
  868. {
  869. assert(ProgressData.InProgress);
  870. FTaskbarList->SetProgressValue(Handle, ProgressData.OverallProgress(), 100);
  871. }
  872. if (FProgressForm->Cancel > ProgressData.Cancel)
  873. {
  874. ProgressData.Cancel = FProgressForm->Cancel;
  875. }
  876. }
  877. }
  878. //---------------------------------------------------------------------------
  879. void __fastcall TCustomScpExplorerForm::OperationComplete(
  880. const TDateTime & StartTime)
  881. {
  882. if (GUIConfiguration->BeepOnFinish &&
  883. (Now() - StartTime > GUIConfiguration->BeepOnFinishAfter))
  884. {
  885. MessageBeep(MB_OK);
  886. }
  887. }
  888. //---------------------------------------------------------------------------
  889. void __fastcall TCustomScpExplorerForm::OperationProgress(
  890. TFileOperationProgressType & ProgressData, TCancelStatus & Cancel)
  891. {
  892. FileOperationProgress(ProgressData, Cancel);
  893. }
  894. //---------------------------------------------------------------------------
  895. bool __fastcall TCustomScpExplorerForm::PanelOperation(TOperationSide /*Side*/,
  896. bool DragDrop)
  897. {
  898. return (!DragDrop && (DropSourceControl == NULL)) ||
  899. (DropSourceControl == RemoteDirView);
  900. }
  901. //---------------------------------------------------------------------------
  902. void __fastcall TCustomScpExplorerForm::DoOperationFinished(
  903. TFileOperation Operation, TOperationSide Side,
  904. bool /*Temp*/, const UnicodeString & FileName, bool Success,
  905. TOnceDoneOperation & OnceDoneOperation)
  906. {
  907. if (!FAutoOperation)
  908. {
  909. // no selection on "/upload", form servers only as event handler
  910. // (it is not displayed)
  911. if (PanelOperation(Side, FDragDropOperation) &&
  912. Visible && (Operation != foCalculateSize) &&
  913. (Operation != foGetProperties) && (Operation != foCalculateChecksum))
  914. {
  915. TCustomDirView * DView = DirView(Side);
  916. UnicodeString FileNameOnly = ExtractFileName(FileName, (Side == osRemote));
  917. TListItem *Item = DView->FindFileItem(FileNameOnly);
  918. // this can happen when local drive is unplugged in the middle of the operation
  919. if (Item != NULL)
  920. {
  921. if (Success) Item->Selected = false;
  922. if (DView->ViewStyle == vsReport)
  923. {
  924. TRect DisplayRect = Item->DisplayRect(drBounds);
  925. if (DisplayRect.Bottom > DView->ClientHeight)
  926. {
  927. DView->Scroll(0, Item->Top - DView->TopItem->Top);
  928. }
  929. }
  930. Item->MakeVisible(false);
  931. }
  932. }
  933. if ((Operation == foCopy) || (Operation == foMove))
  934. {
  935. if (Side == osLocal)
  936. {
  937. Configuration->Usage->Inc(L"UploadedFiles");
  938. }
  939. else
  940. {
  941. Configuration->Usage->Inc(L"DownloadedFiles");
  942. }
  943. }
  944. }
  945. if (Success && (FSynchronizeController != NULL))
  946. {
  947. if (Operation == foCopy)
  948. {
  949. assert(Side == osLocal);
  950. FSynchronizeController->LogOperation(soUpload, FileName);
  951. }
  952. else if (Operation == foDelete)
  953. {
  954. assert(Side == osRemote);
  955. FSynchronizeController->LogOperation(soDelete, FileName);
  956. }
  957. }
  958. if (FProgressForm)
  959. {
  960. OnceDoneOperation = FProgressForm->OnceDoneOperation;
  961. }
  962. }
  963. //---------------------------------------------------------------------------
  964. void __fastcall TCustomScpExplorerForm::OperationFinished(
  965. TFileOperation Operation, TOperationSide Side,
  966. bool Temp, const UnicodeString & FileName, Boolean Success,
  967. TOnceDoneOperation & OnceDoneOperation)
  968. {
  969. DoOperationFinished(Operation, Side, Temp, FileName, Success,
  970. OnceDoneOperation);
  971. }
  972. //---------------------------------------------------------------------------
  973. TCustomDirView * __fastcall TCustomScpExplorerForm::DirView(TOperationSide Side)
  974. {
  975. assert(GetSide(Side) == osRemote);
  976. USEDPARAM(Side);
  977. return RemoteDirView;
  978. }
  979. //---------------------------------------------------------------------------
  980. bool __fastcall TCustomScpExplorerForm::GetEnableFocusedOperation(
  981. TOperationSide Side, int FilesOnly)
  982. {
  983. return DirView(Side)->AnyFileSelected(true, (FilesOnly != 0));
  984. }
  985. //---------------------------------------------------------------------------
  986. bool __fastcall TCustomScpExplorerForm::GetEnableSelectedOperation(
  987. TOperationSide Side, int FilesOnly)
  988. {
  989. return DirView(Side)->AnyFileSelected(false, (FilesOnly != 0));
  990. }
  991. //---------------------------------------------------------------------------
  992. struct THistoryItemData
  993. {
  994. short int Side;
  995. short int Index;
  996. };
  997. //---------------------------------------------------------------------------
  998. void __fastcall TCustomScpExplorerForm::HistoryGo(TOperationSide Side, int Index)
  999. {
  1000. DirView(Side)->HistoryGo(Index);
  1001. }
  1002. //---------------------------------------------------------------------------
  1003. void __fastcall TCustomScpExplorerForm::HistoryItemClick(System::TObject* Sender)
  1004. {
  1005. TTBCustomItem * Item = dynamic_cast<TTBCustomItem *>(Sender);
  1006. THistoryItemData Data = *reinterpret_cast<THistoryItemData*>(&(Item->Tag));
  1007. HistoryGo((TOperationSide)Data.Side, Data.Index);
  1008. }
  1009. //---------------------------------------------------------------------------
  1010. void __fastcall TCustomScpExplorerForm::UpdateHistoryMenu(TOperationSide Side,
  1011. bool Back)
  1012. {
  1013. if (FHistoryMenu[Side == osLocal][Back] != NULL)
  1014. {
  1015. TCustomDirView * DView = DirView(Side);
  1016. TTBXPopupMenu * Menu = FHistoryMenu[Side == osLocal][Back];
  1017. int ICount = Back ? DView->BackCount : DView->ForwardCount;
  1018. if (ICount > 10)
  1019. {
  1020. ICount = 10;
  1021. }
  1022. Menu->Items->Clear();
  1023. THistoryItemData Data;
  1024. Data.Side = Side;
  1025. for (short int i = 1; i <= ICount; i++)
  1026. {
  1027. TTBCustomItem * Item = new TTBXItem(Menu);
  1028. Data.Index = static_cast<short int>(i * (Back ? -1 : 1));
  1029. Item->Caption = MinimizeName(DView->HistoryPath[Data.Index], 50, (Side == osRemote));
  1030. Item->Hint = DView->HistoryPath[Data.Index];
  1031. assert(sizeof(int) == sizeof(THistoryItemData));
  1032. Item->Tag = *reinterpret_cast<int*>(&Data);
  1033. Item->OnClick = HistoryItemClick;
  1034. Menu->Items->Add(Item);
  1035. }
  1036. }
  1037. }
  1038. //---------------------------------------------------------------------------
  1039. TTBXPopupMenu * __fastcall TCustomScpExplorerForm::HistoryMenu(
  1040. TOperationSide Side, bool Back)
  1041. {
  1042. if (FHistoryMenu[Side == osLocal][Back] == NULL)
  1043. {
  1044. // In Pascal the size of TTBXPopupMenu is 132, in C++ 136,
  1045. // operator new allocates memory in Pascal code, but calls inline
  1046. // contructor in C++, leading in problems, the function does
  1047. // both in Pascal code
  1048. FHistoryMenu[Side == osLocal][Back] = CreateTBXPopupMenu(this);
  1049. UpdateHistoryMenu(Side, Back);
  1050. }
  1051. return FHistoryMenu[Side == osLocal][Back];
  1052. }
  1053. //---------------------------------------------------------------------------
  1054. void __fastcall TCustomScpExplorerForm::DirViewHistoryChange(
  1055. TCustomDirView *Sender)
  1056. {
  1057. TOperationSide Side = (Sender == DirView(osRemote) ? osRemote : osLocal);
  1058. UpdateHistoryMenu(Side, true);
  1059. UpdateHistoryMenu(Side, false);
  1060. }
  1061. //---------------------------------------------------------------------------
  1062. bool __fastcall TCustomScpExplorerForm::CustomCommandRemoteAllowed()
  1063. {
  1064. // remote custom commands can be executed only if the server supports shell commands
  1065. // or have secondary shell
  1066. return (FTerminal != NULL) && (FTerminal->IsCapable[fcSecondaryShell] || FTerminal->IsCapable[fcShellAnyCommand]);
  1067. }
  1068. //---------------------------------------------------------------------------
  1069. int __fastcall TCustomScpExplorerForm::BothCustomCommandState(const TCustomCommandType & Command)
  1070. {
  1071. bool Result = FLAGSET(Command.Params, ccLocal);
  1072. if (Result)
  1073. {
  1074. TLocalCustomCommand LocalCustomCommand;
  1075. TInteractiveCustomCommand InteractiveCustomCommand(&LocalCustomCommand);
  1076. UnicodeString Cmd = InteractiveCustomCommand.Complete(Command.Command, false);
  1077. Result =
  1078. LocalCustomCommand.IsFileCommand(Cmd) &&
  1079. LocalCustomCommand.HasLocalFileName(Cmd);
  1080. }
  1081. return Result ? 1 : -1;
  1082. }
  1083. //---------------------------------------------------------------------------
  1084. int __fastcall TCustomScpExplorerForm::CustomCommandState(
  1085. const TCustomCommandType & Command, bool OnFocused)
  1086. {
  1087. int Result;
  1088. TFileCustomCommand RemoteCustomCommand;
  1089. TLocalCustomCommand LocalCustomCommand;
  1090. TFileCustomCommand * NonInteractiveCustomCommand =
  1091. FLAGCLEAR(Command.Params, ccLocal) ? &RemoteCustomCommand : &LocalCustomCommand;
  1092. TInteractiveCustomCommand InteractiveCustomCommand(NonInteractiveCustomCommand);
  1093. UnicodeString Cmd = InteractiveCustomCommand.Complete(Command.Command, false);
  1094. if (FLAGCLEAR(Command.Params, ccLocal))
  1095. {
  1096. Result = CustomCommandRemoteAllowed();
  1097. if (Result)
  1098. {
  1099. // custom command that does not operate with files can be executed anytime ...
  1100. if (!NonInteractiveCustomCommand->IsFileCommand(Cmd))
  1101. {
  1102. // ... but do not show such command in remote file menu
  1103. // (TODO, currently custom commands are in file menu only, so we cannot hide
  1104. // such command, because it won't be accessible from elsewhere)
  1105. Result = OnFocused ? /*-1*/ true : true;
  1106. }
  1107. else
  1108. {
  1109. Result = (FCurrentSide == osRemote) && EnableSelectedOperation[osRemote];
  1110. }
  1111. }
  1112. }
  1113. else
  1114. {
  1115. // custom command that does not operate with files can be executed anytime
  1116. if (!NonInteractiveCustomCommand->IsFileCommand(Cmd))
  1117. {
  1118. Result = true;
  1119. }
  1120. else if (LocalCustomCommand.HasLocalFileName(Cmd))
  1121. {
  1122. // special case is "diff"-style command that can be executed over any side,
  1123. // if we have both sides
  1124. Result = (HasDirView[osLocal] && EnableSelectedOperation[osLocal]) &&
  1125. EnableSelectedOperation[osRemote];
  1126. }
  1127. else
  1128. {
  1129. // other local custom commands can be executed only on remote side
  1130. Result = (FCurrentSide == osRemote) && EnableSelectedOperation[osRemote];
  1131. }
  1132. }
  1133. return Result;
  1134. }
  1135. //---------------------------------------------------------------------------
  1136. void __fastcall TCustomScpExplorerForm::CustomCommand(TStrings * FileList,
  1137. const TCustomCommandType & ACommand, TStrings * ALocalFileList)
  1138. {
  1139. if (FLAGCLEAR(ACommand.Params, ccLocal))
  1140. {
  1141. if (EnsureCommandSessionFallback(fcShellAnyCommand))
  1142. {
  1143. TCustomCommandData Data(Terminal);
  1144. TRemoteCustomCommand RemoteCustomCommand(Data, Terminal->CurrentDirectory);
  1145. TWinInteractiveCustomCommand InteractiveCustomCommand(
  1146. &RemoteCustomCommand, ACommand.Name);
  1147. UnicodeString Command = InteractiveCustomCommand.Complete(ACommand.Command, false);
  1148. Configuration->Usage->Inc(L"LocalCustomCommandRuns");
  1149. bool Capture = FLAGSET(ACommand.Params, ccShowResults) || FLAGSET(ACommand.Params, ccCopyResults);
  1150. TCaptureOutputEvent OutputEvent = NULL;
  1151. assert(FCapturedLog == NULL);
  1152. if (Capture)
  1153. {
  1154. FCapturedLog = new TStringList();
  1155. OutputEvent = TerminalCaptureLog;
  1156. }
  1157. try
  1158. {
  1159. if (!RemoteCustomCommand.IsFileCommand(Command))
  1160. {
  1161. Terminal->AnyCommand(RemoteCustomCommand.Complete(Command, true),
  1162. OutputEvent);
  1163. }
  1164. else
  1165. {
  1166. Terminal->CustomCommandOnFiles(Command, ACommand.Params, FileList, OutputEvent);
  1167. }
  1168. if ((FCapturedLog != NULL) && (FCapturedLog->Count > 0))
  1169. {
  1170. if (FLAGSET(ACommand.Params, ccCopyResults))
  1171. {
  1172. CopyToClipboard(FCapturedLog);
  1173. }
  1174. if (FLAGSET(ACommand.Params, ccShowResults))
  1175. {
  1176. DoConsoleDialog(Terminal, L"", FCapturedLog);
  1177. }
  1178. }
  1179. }
  1180. __finally
  1181. {
  1182. SAFE_DESTROY(FCapturedLog);
  1183. }
  1184. }
  1185. }
  1186. else
  1187. {
  1188. TCustomCommandData Data(Terminal);
  1189. TLocalCustomCommand LocalCustomCommand(Data, Terminal->CurrentDirectory);
  1190. TWinInteractiveCustomCommand InteractiveCustomCommand(
  1191. &LocalCustomCommand, ACommand.Name);
  1192. UnicodeString Command = InteractiveCustomCommand.Complete(ACommand.Command, false);
  1193. Configuration->Usage->Inc(L"RemoteCustomCommandRuns");
  1194. if (!LocalCustomCommand.IsFileCommand(Command))
  1195. {
  1196. ExecuteShellAndWait(LocalCustomCommand.Complete(Command, true));
  1197. }
  1198. else
  1199. {
  1200. TStrings * LocalFileList = NULL;
  1201. TStrings * RemoteFileList = NULL;
  1202. try
  1203. {
  1204. bool FileListCommand = LocalCustomCommand.IsFileListCommand(Command);
  1205. bool LocalFileCommand = LocalCustomCommand.HasLocalFileName(Command);
  1206. if (LocalFileCommand)
  1207. {
  1208. if (ALocalFileList == NULL)
  1209. {
  1210. assert(HasDirView[osLocal]);
  1211. assert(EnableSelectedOperation[osLocal]);
  1212. LocalFileList = DirView(osLocal)->CreateFileList(false, true, NULL);
  1213. }
  1214. else
  1215. {
  1216. LocalFileList = ALocalFileList;
  1217. }
  1218. if (FileListCommand)
  1219. {
  1220. if (LocalFileList->Count != 1)
  1221. {
  1222. throw Exception(LoadStr(CUSTOM_COMMAND_SELECTED_UNMATCH1));
  1223. }
  1224. }
  1225. else
  1226. {
  1227. if ((LocalFileList->Count != 1) &&
  1228. (FileList->Count != 1) &&
  1229. (LocalFileList->Count != FileList->Count))
  1230. {
  1231. throw Exception(LoadStr(CUSTOM_COMMAND_SELECTED_UNMATCH));
  1232. }
  1233. }
  1234. }
  1235. UnicodeString RootTempDir;
  1236. UnicodeString TempDir;
  1237. TemporarilyDownloadFiles(FileList, false, RootTempDir, TempDir, false, false, true);
  1238. try
  1239. {
  1240. RemoteFileList = new TStringList();
  1241. TMakeLocalFileListParams MakeFileListParam;
  1242. MakeFileListParam.FileList = RemoteFileList;
  1243. MakeFileListParam.IncludeDirs = FLAGSET(ACommand.Params, ccApplyToDirectories);
  1244. MakeFileListParam.Recursive =
  1245. FLAGSET(ACommand.Params, ccRecursive) && !FileListCommand;
  1246. ProcessLocalDirectory(TempDir, Terminal->MakeLocalFileList, &MakeFileListParam);
  1247. TFileOperationProgressType Progress(&OperationProgress, &OperationFinished);
  1248. Progress.Start(foCustomCommand, osRemote, FileListCommand ? 1 : FileList->Count);
  1249. assert(FProgressForm != NULL);
  1250. FProgressForm->ReadOnly = true;
  1251. try
  1252. {
  1253. if (FileListCommand)
  1254. {
  1255. UnicodeString LocalFile;
  1256. // MakeFileList does not delimit filenames
  1257. UnicodeString FileList = MakeFileList(RemoteFileList);
  1258. if (LocalFileCommand)
  1259. {
  1260. assert(LocalFileList->Count == 1);
  1261. LocalFile = LocalFileList->Strings[0];
  1262. }
  1263. TCustomCommandData Data(FTerminal);
  1264. TLocalCustomCommand CustomCommand(Data,
  1265. Terminal->CurrentDirectory, L"", LocalFile, FileList);
  1266. ExecuteShellAndWait(CustomCommand.Complete(Command, true));
  1267. }
  1268. else if (LocalFileCommand)
  1269. {
  1270. if (LocalFileList->Count == 1)
  1271. {
  1272. UnicodeString LocalFile = LocalFileList->Strings[0];
  1273. for (int Index = 0; Index < RemoteFileList->Count; Index++)
  1274. {
  1275. UnicodeString FileName = RemoteFileList->Strings[Index];
  1276. TCustomCommandData Data(FTerminal);
  1277. TLocalCustomCommand CustomCommand(Data,
  1278. Terminal->CurrentDirectory, FileName, LocalFile, L"");
  1279. ExecuteShellAndWait(CustomCommand.Complete(Command, true));
  1280. }
  1281. }
  1282. else if (RemoteFileList->Count == 1)
  1283. {
  1284. UnicodeString FileName = RemoteFileList->Strings[0];
  1285. for (int Index = 0; Index < LocalFileList->Count; Index++)
  1286. {
  1287. TCustomCommandData Data(FTerminal);
  1288. TLocalCustomCommand CustomCommand(
  1289. Data, Terminal->CurrentDirectory,
  1290. FileName, LocalFileList->Strings[Index], L"");
  1291. ExecuteShellAndWait(CustomCommand.Complete(Command, true));
  1292. }
  1293. }
  1294. else
  1295. {
  1296. if (LocalFileList->Count != RemoteFileList->Count)
  1297. {
  1298. throw Exception(LoadStr(CUSTOM_COMMAND_PAIRS_DOWNLOAD_FAILED));
  1299. }
  1300. for (int Index = 0; Index < LocalFileList->Count; Index++)
  1301. {
  1302. UnicodeString FileName = RemoteFileList->Strings[Index];
  1303. TCustomCommandData Data(FTerminal);
  1304. TLocalCustomCommand CustomCommand(
  1305. Data, Terminal->CurrentDirectory,
  1306. FileName, LocalFileList->Strings[Index], L"");
  1307. ExecuteShellAndWait(CustomCommand.Complete(Command, true));
  1308. }
  1309. }
  1310. }
  1311. else
  1312. {
  1313. for (int Index = 0; Index < RemoteFileList->Count; Index++)
  1314. {
  1315. TCustomCommandData Data(FTerminal);
  1316. TLocalCustomCommand CustomCommand(Data,
  1317. Terminal->CurrentDirectory, RemoteFileList->Strings[Index], L"", L"");
  1318. ExecuteShellAndWait(CustomCommand.Complete(Command, true));
  1319. }
  1320. }
  1321. }
  1322. __finally
  1323. {
  1324. Progress.Stop();
  1325. }
  1326. }
  1327. __finally
  1328. {
  1329. RecursiveDeleteFile(ExcludeTrailingBackslash(RootTempDir), false);
  1330. }
  1331. }
  1332. __finally
  1333. {
  1334. delete RemoteFileList;
  1335. if (LocalFileList != ALocalFileList)
  1336. {
  1337. delete LocalFileList;
  1338. }
  1339. }
  1340. }
  1341. }
  1342. }
  1343. //---------------------------------------------------------------------------
  1344. void __fastcall TCustomScpExplorerForm::BothCustomCommand(
  1345. const TCustomCommandType & Command)
  1346. {
  1347. assert(FCustomCommandLocalFileList != NULL);
  1348. assert(FCustomCommandRemoteFileList != NULL);
  1349. assert(FCustomCommandLocalFileList->Count == FCustomCommandRemoteFileList->Count);
  1350. TStrings * LocalFileList = new TStringList();
  1351. TStrings * RemoteFileList = new TStringList();
  1352. try
  1353. {
  1354. for (int Index = 0; Index < FCustomCommandLocalFileList->Count; Index++)
  1355. {
  1356. LocalFileList->Clear();
  1357. LocalFileList->AddObject(
  1358. FCustomCommandLocalFileList->Strings[Index],
  1359. FCustomCommandLocalFileList->Objects[Index]);
  1360. RemoteFileList->Clear();
  1361. RemoteFileList->AddObject(
  1362. FCustomCommandRemoteFileList->Strings[Index],
  1363. FCustomCommandRemoteFileList->Objects[Index]);
  1364. CustomCommand(RemoteFileList, Command, LocalFileList);
  1365. }
  1366. }
  1367. __finally
  1368. {
  1369. delete LocalFileList;
  1370. delete RemoteFileList;
  1371. }
  1372. }
  1373. //---------------------------------------------------------------------------
  1374. void __fastcall TCustomScpExplorerForm::CustomCommandMenu(
  1375. TObject * Sender, const TPoint & MousePos,
  1376. TStrings * LocalFileList, TStrings * RemoteFileList)
  1377. {
  1378. FCustomCommandMenu->Items->Clear();
  1379. delete FCustomCommandLocalFileList;
  1380. delete FCustomCommandRemoteFileList;
  1381. // takeover ownership,
  1382. // the lists must survive the MenuPopup as OnClick occurs only after it exits
  1383. FCustomCommandLocalFileList = LocalFileList;
  1384. FCustomCommandRemoteFileList = RemoteFileList;
  1385. NonVisualDataModule->CreateCustomCommandsMenu(FCustomCommandMenu->Items, false, false, true);
  1386. MenuPopup(FCustomCommandMenu, MousePos, dynamic_cast<TComponent *>(Sender));
  1387. }
  1388. //---------------------------------------------------------------------------
  1389. void __fastcall TCustomScpExplorerForm::TerminalCaptureLog(
  1390. const UnicodeString & AddedLine, bool /*StdError*/)
  1391. {
  1392. assert(FCapturedLog != NULL);
  1393. FCapturedLog->Add(AddedLine);
  1394. }
  1395. //---------------------------------------------------------------------------
  1396. bool __fastcall TCustomScpExplorerForm::IsFileControl(TObject * Control,
  1397. TOperationSide Side)
  1398. {
  1399. return (Side == osRemote) &&
  1400. ((Control == RemoteDirView) || (Control == RemoteDriveView));
  1401. }
  1402. //---------------------------------------------------------------------------
  1403. void __fastcall TCustomScpExplorerForm::RemoteDirViewContextPopup(
  1404. TObject * /*Sender*/, const TPoint &MousePos, bool &Handled)
  1405. {
  1406. TListItem * Item = RemoteDirView->ItemFocused;
  1407. if ((RemoteDirView->GetItemAt(MousePos.x, MousePos.y) == Item) &&
  1408. RemoteDirView->AnyFileSelected(true, false))
  1409. {
  1410. TPoint ScreenPoint, ClientPoint;
  1411. ClientPoint = ((MousePos.x < 0) && (MousePos.y < 0)) ?
  1412. TPoint(0, 0) : MousePos;
  1413. ScreenPoint = RemoteDirView->ClientToScreen(ClientPoint);
  1414. #define DEFAULTITEM(ITEM, DEFAULT) \
  1415. { \
  1416. TTBItemOptions O; \
  1417. O = NonVisualDataModule->ITEM->Options; \
  1418. if ((DEFAULT) && Terminal->ResolvingSymlinks && \
  1419. !RemoteDirView->ItemIsDirectory(Item)) \
  1420. NonVisualDataModule->ITEM->Options = O << tboDefault; \
  1421. else \
  1422. NonVisualDataModule->ITEM->Options = O >> tboDefault; \
  1423. }
  1424. DEFAULTITEM(CurrentOpenMenuItem, WinConfiguration->DoubleClickAction == dcaOpen);
  1425. DEFAULTITEM(CurrentEditMenuItem, WinConfiguration->DoubleClickAction == dcaEdit);
  1426. DEFAULTITEM(CurrentCopyMenuItem, WinConfiguration->DoubleClickAction == dcaCopy);
  1427. #undef DEFAULTITEM
  1428. NonVisualDataModule->CurrentOpenMenuItem->Visible = WinConfiguration->ExpertMode;
  1429. NonVisualDataModule->CurrentEditMenuItem->Visible = WinConfiguration->ExpertMode;
  1430. reinterpret_cast<TPopupMenu*>(GetComponent(fcRemotePopup))->Popup(
  1431. ScreenPoint.x, ScreenPoint.y);
  1432. }
  1433. Handled = true;
  1434. }
  1435. //---------------------------------------------------------------------------
  1436. void __fastcall TCustomScpExplorerForm::ReloadLocalDirectory(const UnicodeString Directory)
  1437. {
  1438. }
  1439. //---------------------------------------------------------------------------
  1440. void __fastcall TCustomScpExplorerForm::BatchStart(void *& /*Storage*/)
  1441. {
  1442. assert(FErrorList == NULL);
  1443. if (WinConfiguration->ContinueOnError)
  1444. {
  1445. FErrorList = new TStringList();
  1446. }
  1447. }
  1448. //---------------------------------------------------------------------------
  1449. void __fastcall TCustomScpExplorerForm::BatchEnd(void * /*Storage*/)
  1450. {
  1451. if (FErrorList)
  1452. {
  1453. HandleErrorList(FErrorList);
  1454. }
  1455. }
  1456. //---------------------------------------------------------------------------
  1457. void __fastcall TCustomScpExplorerForm::UpdateCopyParamCounters(
  1458. const TCopyParamType & CopyParam)
  1459. {
  1460. if (!CopyParam.IncludeFileMask.Masks.IsEmpty())
  1461. {
  1462. Configuration->Usage->Inc(L"FileMaskUses");
  1463. }
  1464. if (IsEffectiveFileNameMask(CopyParam.FileMask))
  1465. {
  1466. Configuration->Usage->Inc(L"OperationMaskUses");
  1467. }
  1468. }
  1469. //---------------------------------------------------------------------------
  1470. bool __fastcall TCustomScpExplorerForm::ExecuteFileOperation(TFileOperation Operation,
  1471. TOperationSide Side, TStrings * FileList, bool NoConfirmation, void * Param)
  1472. {
  1473. void * BatchStorage;
  1474. BatchStart(BatchStorage);
  1475. bool Result;
  1476. try
  1477. {
  1478. if ((Operation == foCopy) || (Operation == foMove))
  1479. {
  1480. TTransferDirection Direction = (Side == osLocal ? tdToRemote : tdToLocal);
  1481. TTransferType Type = (Operation == foCopy ? ttCopy : ttMove);
  1482. UnicodeString TargetDirectory;
  1483. bool Temp = false;
  1484. bool DragDrop = false;
  1485. if (Param != NULL)
  1486. {
  1487. TTransferOperationParam& TParam =
  1488. *static_cast<TTransferOperationParam*>(Param);
  1489. TargetDirectory = TParam.TargetDirectory;
  1490. Temp = TParam.Temp;
  1491. DragDrop = TParam.DragDrop;
  1492. }
  1493. TGUICopyParamType CopyParam = GUIConfiguration->CurrentCopyParam;
  1494. Result =
  1495. CopyParamDialog(Direction, Type, Temp, FileList, TargetDirectory,
  1496. CopyParam, !NoConfirmation, DragDrop);
  1497. if (Result)
  1498. {
  1499. assert(Terminal);
  1500. bool SelectionRestored = false;
  1501. TCustomDirView * DView = NULL;
  1502. if (HasDirView[Side])
  1503. {
  1504. DView = DirView(Side);
  1505. DView->SaveSelection();
  1506. DView->SaveSelectedNames();
  1507. }
  1508. UpdateCopyParamCounters(CopyParam);
  1509. try
  1510. {
  1511. if (Side == osLocal)
  1512. {
  1513. int Params =
  1514. FLAGMASK(Operation == foMove, cpDelete) |
  1515. FLAGMASK(CopyParam.NewerOnly, cpNewerOnly) |
  1516. FLAGMASK(Temp, cpTemporary);
  1517. Terminal->CopyToRemote(FileList, TargetDirectory, &CopyParam, Params);
  1518. if (Operation == foMove)
  1519. {
  1520. ReloadLocalDirectory();
  1521. if (DView != NULL)
  1522. {
  1523. DView->RestoreSelection();
  1524. }
  1525. SelectionRestored = true;
  1526. }
  1527. }
  1528. else
  1529. {
  1530. try
  1531. {
  1532. int Params =
  1533. (Operation == foMove ? cpDelete : 0) |
  1534. (CopyParam.NewerOnly ? cpNewerOnly : 0);
  1535. Terminal->CopyToLocal(FileList, TargetDirectory, &CopyParam,
  1536. Params);
  1537. }
  1538. __finally
  1539. {
  1540. if (Operation == foMove)
  1541. {
  1542. if (DView != NULL)
  1543. {
  1544. DView->RestoreSelection();
  1545. }
  1546. SelectionRestored = true;
  1547. }
  1548. ReloadLocalDirectory(TargetDirectory);
  1549. }
  1550. }
  1551. }
  1552. __finally
  1553. {
  1554. if (!SelectionRestored && (DView != NULL))
  1555. {
  1556. DView->DiscardSavedSelection();
  1557. }
  1558. }
  1559. }
  1560. }
  1561. else if (Operation == foRename)
  1562. {
  1563. assert(DirView(Side)->ItemFocused);
  1564. DirView(Side)->ItemFocused->EditCaption();
  1565. Result = true;
  1566. }
  1567. else if (Operation == foDelete)
  1568. {
  1569. assert(FileList->Count);
  1570. bool Alternative = bool(Param);
  1571. bool Recycle;
  1572. if (Side == osLocal)
  1573. {
  1574. Recycle = (WinConfiguration->DeleteToRecycleBin != Alternative);
  1575. }
  1576. else
  1577. {
  1578. Recycle = (Terminal->SessionData->DeleteToRecycleBin != Alternative) &&
  1579. !Terminal->SessionData->RecycleBinPath.IsEmpty() &&
  1580. !Terminal->IsRecycledFile(FileList->Strings[0]);
  1581. }
  1582. Result =
  1583. !(Recycle ? WinConfiguration->ConfirmRecycling : WinConfiguration->ConfirmDeleting);
  1584. if (!Result)
  1585. {
  1586. UnicodeString Query;
  1587. if (FileList->Count == 1)
  1588. {
  1589. if (Side == osLocal)
  1590. {
  1591. Query = ExtractFileName(FileList->Strings[0]);
  1592. }
  1593. else
  1594. {
  1595. Query = UnixExtractFileName(FileList->Strings[0]);
  1596. }
  1597. Query = FMTLOAD(
  1598. (Recycle ? CONFIRM_RECYCLE_FILE : CONFIRM_DELETE_FILE), (Query));
  1599. }
  1600. else
  1601. {
  1602. Query = FMTLOAD(
  1603. (Recycle ? CONFIRM_RECYCLE_FILES : CONFIRM_DELETE_FILES), (FileList->Count));
  1604. }
  1605. TMessageParams Params(mpNeverAskAgainCheck);
  1606. unsigned int Answer = MessageDialog(Query, qtConfirmation,
  1607. qaOK | qaCancel, HELP_NONE, &Params);
  1608. if (Answer == qaNeverAskAgain)
  1609. {
  1610. Result = true;
  1611. if (Recycle)
  1612. {
  1613. WinConfiguration->ConfirmRecycling = false;
  1614. }
  1615. else
  1616. {
  1617. WinConfiguration->ConfirmDeleting = false;
  1618. }
  1619. }
  1620. else
  1621. {
  1622. Result = (Answer == qaOK);
  1623. }
  1624. }
  1625. if (Result)
  1626. {
  1627. DeleteFiles(Side, FileList, FLAGMASK(Alternative, dfAlternative));
  1628. }
  1629. }
  1630. else if (Operation == foSetProperties)
  1631. {
  1632. RemoteDirView->SaveSelectedNames();
  1633. Result = SetProperties(Side, FileList);
  1634. }
  1635. else if (Operation == foCustomCommand)
  1636. {
  1637. assert(Param);
  1638. assert(Side == osRemote);
  1639. RemoteDirView->SaveSelectedNames();
  1640. const TCustomCommandType * Command = static_cast<const TCustomCommandType*>(Param);
  1641. CustomCommand(FileList, *Command, NULL);
  1642. Result = true;
  1643. }
  1644. else if ((Operation == foRemoteMove) || (Operation == foRemoteCopy))
  1645. {
  1646. assert(Side == osRemote);
  1647. Result = RemoteTransferFiles(FileList, NoConfirmation,
  1648. (Operation == foRemoteMove), reinterpret_cast<TTerminal *>(Param));
  1649. }
  1650. else
  1651. {
  1652. assert(false);
  1653. }
  1654. }
  1655. __finally
  1656. {
  1657. BatchEnd(BatchStorage);
  1658. }
  1659. return Result;
  1660. }
  1661. //---------------------------------------------------------------------------
  1662. TOperationSide __fastcall TCustomScpExplorerForm::GetSide(TOperationSide Side)
  1663. {
  1664. if (Side == osCurrent)
  1665. {
  1666. Side = FCurrentSide;
  1667. }
  1668. return Side;
  1669. }
  1670. //---------------------------------------------------------------------------
  1671. bool __fastcall TCustomScpExplorerForm::ExecuteFileOperation(TFileOperation Operation,
  1672. TOperationSide Side, bool OnFocused, bool NoConfirmation, void * Param)
  1673. {
  1674. Side = GetSide(Side);
  1675. bool Result;
  1676. TStrings * FileList = DirView(Side)->CreateFileList(OnFocused, (Side == osLocal), NULL);
  1677. try
  1678. {
  1679. Result = ExecuteFileOperation(Operation, Side, FileList, NoConfirmation, Param);
  1680. }
  1681. __finally
  1682. {
  1683. delete FileList;
  1684. }
  1685. return Result;
  1686. }
  1687. //---------------------------------------------------------------------------
  1688. void __fastcall TCustomScpExplorerForm::ExecuteFileOperationCommand(
  1689. TFileOperation Operation, TOperationSide Side, bool OnFocused,
  1690. bool NoConfirmation, void * Param)
  1691. {
  1692. if (ExecuteFileOperation(Operation, Side, OnFocused, NoConfirmation, Param))
  1693. {
  1694. if ((Operation == foCopy) || (Operation == foMove))
  1695. {
  1696. if (GetSide(Side) == osLocal)
  1697. {
  1698. Configuration->Usage->Inc(L"UploadsCommand");
  1699. }
  1700. else
  1701. {
  1702. Configuration->Usage->Inc(L"DownloadsCommand");
  1703. }
  1704. }
  1705. }
  1706. }
  1707. //---------------------------------------------------------------------------
  1708. void __fastcall TCustomScpExplorerForm::HandleErrorList(TStringList *& ErrorList)
  1709. {
  1710. try
  1711. {
  1712. if (ErrorList->Count)
  1713. {
  1714. if (MessageDialog(FMTLOAD(ERROR_LIST_COUNT, (ErrorList->Count)), qtError,
  1715. qaOK | qaCancel, HELP_NONE) == qaOK)
  1716. {
  1717. unsigned int Answer;
  1718. int Index = 0;
  1719. do
  1720. {
  1721. assert(Index >= 0 && Index < ErrorList->Count);
  1722. TQueryButtonAlias Aliases[2];
  1723. Aliases[0].Button = qaYes;
  1724. Aliases[0].Alias = LoadStr(PREV_BUTTON);
  1725. Aliases[1].Button = qaNo;
  1726. Aliases[1].Alias = LoadStr(NEXT_BUTTON);
  1727. TMessageParams Params;
  1728. Params.Aliases = Aliases;
  1729. Params.AliasesCount = LENOF(Aliases);
  1730. Answer = MoreMessageDialog(
  1731. FMTLOAD(ERROR_LIST_NUMBER, (Index+1, ErrorList->Count, ErrorList->Strings[Index])),
  1732. dynamic_cast<TStrings *>(ErrorList->Objects[Index]), qtError,
  1733. (Index ? qaYes : 0) | (Index < ErrorList->Count - 1 ? qaNo : 0) |
  1734. qaOK, HELP_NONE, &Params);
  1735. if (Answer == qaNo)
  1736. {
  1737. Index++;
  1738. }
  1739. if (Answer == qaYes)
  1740. {
  1741. Index--;
  1742. }
  1743. }
  1744. while (Answer != qaOK);
  1745. }
  1746. }
  1747. }
  1748. __finally
  1749. {
  1750. TStrings * List = ErrorList;
  1751. ErrorList = NULL;
  1752. for (int i = 0; i < List->Count; i++)
  1753. {
  1754. delete List->Objects[i];
  1755. }
  1756. delete List;
  1757. }
  1758. }
  1759. //---------------------------------------------------------------------------
  1760. void __fastcall TCustomScpExplorerForm::EditNew(TOperationSide Side)
  1761. {
  1762. assert(!WinConfiguration->DisableOpenEdit);
  1763. Side = GetSide(Side);
  1764. TCustomDirView * CurrentDirView = DirView(osCurrent);
  1765. TListItem * FocusedItem = CurrentDirView->ItemFocused;
  1766. UnicodeString Name;
  1767. if ((FocusedItem != NULL) && !CurrentDirView->ItemIsParentDirectory(FocusedItem))
  1768. {
  1769. Name = CurrentDirView->ItemFileName(FocusedItem);
  1770. }
  1771. else
  1772. {
  1773. Name = LoadStr(NEW_FILE);
  1774. }
  1775. TStrings * History = CustomWinConfiguration->History[L"EditFile"];
  1776. if (InputDialog(LoadStr(EDIT_FILE_CAPTION), LoadStr(EDIT_FILE_PROMPT), Name,
  1777. HELP_EDIT_NEW, History, true))
  1778. {
  1779. CustomWinConfiguration->History[L"EditFile"] = History;
  1780. UnicodeString TargetFileName;
  1781. UnicodeString LocalFileName;
  1782. UnicodeString RootTempDir;
  1783. UnicodeString TempDir;
  1784. UnicodeString RemoteDirectory;
  1785. if (Side == osRemote)
  1786. {
  1787. Name = AbsolutePath(FTerminal->CurrentDirectory, Name);
  1788. TRemoteFile * File = NULL;
  1789. if (FTerminal->FileExists(Name, &File))
  1790. {
  1791. try
  1792. {
  1793. // needed for checking filemasks, as there's no directory object
  1794. // associated with the file object
  1795. File->FullFileName = Name;
  1796. TFileMasks::TParams MaskParams;
  1797. MaskParams.Size = File->Size;
  1798. MaskParams.Modification = File->Modification;
  1799. ExecuteFile(Side, efDefaultEditor, NULL, Name, File, MaskParams);
  1800. return;
  1801. }
  1802. __finally
  1803. {
  1804. delete File;
  1805. }
  1806. }
  1807. RemoteDirectory = UnixExtractFilePath(Name);
  1808. TemporaryDirectoryForRemoteFiles(
  1809. RemoteDirectory, GUIConfiguration->CurrentCopyParam, TempDir, RootTempDir);
  1810. TargetFileName = UnixExtractFileName(Name);
  1811. LocalFileName = TempDir +
  1812. GUIConfiguration->CurrentCopyParam.ChangeFileName(TargetFileName, osRemote, false);
  1813. }
  1814. else
  1815. {
  1816. if (ExtractFilePath(Name).IsEmpty())
  1817. {
  1818. LocalFileName = IncludeTrailingBackslash(DirView(Side)->PathName) + Name;
  1819. }
  1820. else
  1821. {
  1822. LocalFileName = ExpandFileName(Name);
  1823. }
  1824. TargetFileName = ExtractFileName(Name);
  1825. }
  1826. if (!FileExists(LocalFileName))
  1827. {
  1828. int File = FileCreate(LocalFileName);
  1829. if (File < 0)
  1830. {
  1831. if (!RootTempDir.IsEmpty())
  1832. {
  1833. RecursiveDeleteFile(ExcludeTrailingBackslash(RootTempDir), false);
  1834. }
  1835. throw Exception(FMTLOAD(CREATE_FILE_ERROR, (LocalFileName)));
  1836. }
  1837. else
  1838. {
  1839. FileClose(File);
  1840. }
  1841. }
  1842. TExecuteFileBy ExecuteFileBy = efDefaultEditor;
  1843. const TEditorData * ExternalEditor = NULL;
  1844. TFileMasks::TParams MaskParams; // size not known
  1845. ExecuteFileNormalize(ExecuteFileBy, ExternalEditor, TargetFileName,
  1846. false, MaskParams);
  1847. CustomExecuteFile(Side, ExecuteFileBy, LocalFileName, TargetFileName,
  1848. ExternalEditor, RootTempDir, RemoteDirectory);
  1849. }
  1850. }
  1851. //---------------------------------------------------------------------------
  1852. bool __fastcall TCustomScpExplorerForm::RemoteExecuteForceText(
  1853. TExecuteFileBy ExecuteFileBy, const TEditorData * ExternalEditor)
  1854. {
  1855. assert((ExecuteFileBy == efExternalEditor) ==
  1856. ((ExternalEditor != NULL) && (ExternalEditor->Editor == edExternal)));
  1857. assert(ExecuteFileBy != efDefaultEditor);
  1858. return
  1859. ((ExecuteFileBy == efInternalEditor)) ||
  1860. ((ExecuteFileBy == efExternalEditor) && ExternalEditor->ExternalEditorText);
  1861. }
  1862. //---------------------------------------------------------------------------
  1863. void __fastcall TCustomScpExplorerForm::CustomExecuteFile(TOperationSide Side,
  1864. TExecuteFileBy ExecuteFileBy, UnicodeString FileName, UnicodeString OriginalFileName,
  1865. const TEditorData * ExternalEditor, UnicodeString LocalRootDirectory,
  1866. UnicodeString RemoteDirectory)
  1867. {
  1868. assert(!WinConfiguration->DisableOpenEdit);
  1869. assert((ExecuteFileBy == efExternalEditor) ==
  1870. ((ExternalEditor != NULL) && (ExternalEditor->Editor == edExternal)));
  1871. assert(ExecuteFileBy != efDefaultEditor);
  1872. Side = GetSide(Side);
  1873. TEditedFileData Data;
  1874. if (Side == osRemote)
  1875. {
  1876. Data.Terminal = Terminal;
  1877. Data.Queue = Queue;
  1878. Data.ForceText = RemoteExecuteForceText(ExecuteFileBy, ExternalEditor);
  1879. Data.RemoteDirectory = RemoteDirectory;
  1880. Data.SessionName = Terminal->SessionData->SessionName;
  1881. Data.LocalRootDirectory = LocalRootDirectory;
  1882. Data.OriginalFileName = OriginalFileName;
  1883. Data.Command = L""; // will be changed later for external editor
  1884. }
  1885. if (ExecuteFileBy == efInternalEditor)
  1886. {
  1887. if (Side == osRemote)
  1888. {
  1889. UnicodeString Caption = UnixIncludeTrailingBackslash(RemoteDirectory) + OriginalFileName +
  1890. L" - " + Terminal->SessionData->SessionName;
  1891. TForm * Editor;
  1892. try
  1893. {
  1894. Editor = ShowEditorForm(FileName, this, FEditorManager->FileChanged,
  1895. FEditorManager->FileReload, FEditorManager->FileClosed, Caption);
  1896. }
  1897. catch(...)
  1898. {
  1899. try
  1900. {
  1901. RecursiveDeleteFile(ExcludeTrailingBackslash(LocalRootDirectory), false);
  1902. }
  1903. catch(...)
  1904. {
  1905. }
  1906. throw;
  1907. }
  1908. FEditorManager->AddFileInternal(FileName, Data, Editor);
  1909. }
  1910. else
  1911. {
  1912. FLocalEditors->Add(ShowEditorForm(FileName, this, NULL, NULL, LocalEditorClosed, L""));
  1913. }
  1914. }
  1915. else
  1916. {
  1917. HANDLE Process;
  1918. if (ExecuteFileBy == efExternalEditor)
  1919. {
  1920. UnicodeString Program, Params, Dir;
  1921. Data.Command = ExternalEditor->ExternalEditor;
  1922. ReformatFileNameCommand(Data.Command);
  1923. SplitCommand(Data.Command, Program, Params, Dir);
  1924. Params = ExpandFileNameCommand(Params, FileName);
  1925. Program = ExpandEnvironmentVariables(Program);
  1926. if (!ExecuteShell(Program, Params, Process))
  1927. {
  1928. throw Exception(FMTLOAD(EDITOR_ERROR, (Program)));
  1929. }
  1930. }
  1931. else
  1932. {
  1933. assert(Side == osRemote);
  1934. if (!ExecuteShell(FileName, L"", Process))
  1935. {
  1936. throw Exception(FMTLOAD(EXECUTE_FILE_ERROR, (FileName)));
  1937. }
  1938. }
  1939. if ((Side == osLocal) ||
  1940. ((ExecuteFileBy == efShell) &&
  1941. !WinConfiguration->Editor.SDIShellEditor) ||
  1942. ((ExecuteFileBy == efExternalEditor) &&
  1943. !ExternalEditor->SDIExternalEditor))
  1944. {
  1945. // no need for handle
  1946. if (Process != NULL)
  1947. {
  1948. CHECK(CloseHandle(Process));
  1949. }
  1950. Process = INVALID_HANDLE_VALUE;
  1951. }
  1952. else
  1953. {
  1954. if (Process == NULL)
  1955. {
  1956. throw ExtException(LoadStr(OPEN_FILE_NO_PROCESS2), L"", HELP_OPEN_FILE_NO_PROCESS);
  1957. }
  1958. }
  1959. if (Side == osRemote)
  1960. {
  1961. FEditorManager->AddFileExternal(FileName, Data, Process);
  1962. }
  1963. }
  1964. }
  1965. //---------------------------------------------------------------------------
  1966. void __fastcall TCustomScpExplorerForm::LocalEditorClosed(TObject * Sender, bool /*Forced*/)
  1967. {
  1968. CHECK(FLocalEditors->Extract(Sender) >= 0);
  1969. }
  1970. //---------------------------------------------------------------------------
  1971. void __fastcall TCustomScpExplorerForm::TemporaryDirectoryForRemoteFiles(
  1972. UnicodeString RemoteDirectory, TCopyParamType CopyParam,
  1973. UnicodeString & Result, UnicodeString & RootDirectory)
  1974. {
  1975. RootDirectory = IncludeTrailingBackslash(WinConfiguration->TemporaryDir());
  1976. Result = RootDirectory;
  1977. if (WinConfiguration->TemporaryDirectoryAppendSession)
  1978. {
  1979. Result = IncludeTrailingBackslash(Result + CopyParam.ValidLocalPath(Terminal->SessionData->SessionName));
  1980. }
  1981. if (WinConfiguration->TemporaryDirectoryAppendPath)
  1982. {
  1983. if (!RemoteDirectory.IsEmpty() && (RemoteDirectory[1] == L'/'))
  1984. {
  1985. RemoteDirectory.Delete(1, 1);
  1986. }
  1987. Result = IncludeTrailingBackslash(Result + CopyParam.ValidLocalPath(FromUnixPath(RemoteDirectory)));
  1988. }
  1989. if (!ForceDirectories(Result))
  1990. {
  1991. throw EOSExtException(FMTLOAD(CREATE_TEMP_DIR_ERROR, (Result)));
  1992. }
  1993. }
  1994. //---------------------------------------------------------------------------
  1995. void __fastcall TCustomScpExplorerForm::TemporarilyDownloadFiles(
  1996. TStrings * FileList, bool ForceText, UnicodeString & RootTempDir, UnicodeString & TempDir,
  1997. bool AllFiles, bool GetTargetNames, bool AutoOperation)
  1998. {
  1999. TCopyParamType CopyParam = GUIConfiguration->CurrentCopyParam;
  2000. if (ForceText)
  2001. {
  2002. CopyParam.TransferMode = tmAscii;
  2003. }
  2004. // do not forget to add additional options to ExecutedFileChanged, FAR and SS
  2005. CopyParam.FileNameCase = ncNoChange;
  2006. CopyParam.PreserveReadOnly = false;
  2007. CopyParam.ReplaceInvalidChars = true;
  2008. CopyParam.FileMask = L"";
  2009. if (AllFiles)
  2010. {
  2011. CopyParam.IncludeFileMask = TFileMasks();
  2012. }
  2013. if (RootTempDir.IsEmpty())
  2014. {
  2015. TemporaryDirectoryForRemoteFiles(FTerminal->CurrentDirectory, CopyParam, TempDir, RootTempDir);
  2016. }
  2017. assert(!FAutoOperation);
  2018. FAutoOperation = AutoOperation;
  2019. Terminal->ExceptionOnFail = true;
  2020. try
  2021. {
  2022. try
  2023. {
  2024. // turn off confirmations, as for MDI editors we may possibly download
  2025. // the same file over
  2026. Terminal->CopyToLocal(FileList, TempDir, &CopyParam,
  2027. cpNoConfirmation | cpTemporary);
  2028. if (GetTargetNames)
  2029. {
  2030. for (int i = 0; i < FileList->Count; i++)
  2031. {
  2032. FileList->Strings[i] =
  2033. CopyParam.ChangeFileName(UnixExtractFileName(FileList->Strings[i]), osRemote, false);
  2034. }
  2035. }
  2036. }
  2037. catch(...)
  2038. {
  2039. try
  2040. {
  2041. RecursiveDeleteFile(ExcludeTrailingBackslash(RootTempDir), false);
  2042. }
  2043. catch(...)
  2044. {
  2045. }
  2046. throw;
  2047. }
  2048. }
  2049. __finally
  2050. {
  2051. FAutoOperation = false;
  2052. Terminal->ExceptionOnFail = false;
  2053. }
  2054. }
  2055. //---------------------------------------------------------------------------
  2056. void __fastcall TCustomScpExplorerForm::ExecuteFileNormalize(
  2057. TExecuteFileBy & ExecuteFileBy, const TEditorData *& ExternalEditor,
  2058. const UnicodeString & FileName, bool Local, const TFileMasks::TParams & MaskParams)
  2059. {
  2060. if (ExecuteFileBy == efDefaultEditor)
  2061. {
  2062. const TEditorPreferences * Editor =
  2063. WinConfiguration->DefaultEditorForFile(FileName, Local, MaskParams);
  2064. if ((Editor == NULL) || (Editor->Data->Editor == edInternal))
  2065. {
  2066. ExecuteFileBy = efInternalEditor;
  2067. ExternalEditor = NULL;
  2068. }
  2069. else if (Editor->Data->Editor == edOpen)
  2070. {
  2071. ExecuteFileBy = efShell;
  2072. ExternalEditor = NULL;
  2073. }
  2074. else
  2075. {
  2076. ExecuteFileBy = efExternalEditor;
  2077. ExternalEditor = Editor->Data;
  2078. }
  2079. }
  2080. }
  2081. //---------------------------------------------------------------------------
  2082. void __fastcall TCustomScpExplorerForm::ExecuteFile(TOperationSide Side,
  2083. TExecuteFileBy ExecuteFileBy, const TEditorData * ExternalEditor,
  2084. UnicodeString FullFileName, TObject * Object, const TFileMasks::TParams & MaskParams)
  2085. {
  2086. UnicodeString OriginalFileName;
  2087. UnicodeString LocalRootDirectory;
  2088. UnicodeString RemoteDirectory;
  2089. ExecuteFileNormalize(ExecuteFileBy, ExternalEditor, FullFileName,
  2090. (Side == osLocal), MaskParams);
  2091. UnicodeString Counter;
  2092. UnicodeString LocalFileName;
  2093. if (Side == osRemote)
  2094. {
  2095. OriginalFileName = UnixExtractFileName(FullFileName);
  2096. RemoteDirectory = UnixExtractFilePath(FullFileName);
  2097. TObject * Token = NULL;
  2098. UnicodeString LocalDirectory;
  2099. if (!FEditorManager->CanAddFile(RemoteDirectory, OriginalFileName,
  2100. Terminal->SessionData->SessionName, Token, LocalRootDirectory,
  2101. LocalDirectory))
  2102. {
  2103. if (Token != NULL)
  2104. {
  2105. TForm * Form = dynamic_cast<TForm *>(Token);
  2106. if (Form->WindowState == wsMinimized)
  2107. {
  2108. ShowWindow(Form->Handle, SW_RESTORE);
  2109. }
  2110. else
  2111. {
  2112. Form->SetFocus();
  2113. }
  2114. Abort();
  2115. }
  2116. else
  2117. {
  2118. throw Exception(FMTLOAD(ALREADY_EDITED_EXTERNALLY_OR_UPLOADED, (OriginalFileName)));
  2119. }
  2120. }
  2121. TStringList * FileList1 = new TStringList();
  2122. try
  2123. {
  2124. FileList1->AddObject(FullFileName, Object);
  2125. TemporarilyDownloadFiles(FileList1,
  2126. RemoteExecuteForceText(ExecuteFileBy, ExternalEditor),
  2127. LocalRootDirectory, LocalDirectory, true, true, true);
  2128. LocalFileName = LocalDirectory + FileList1->Strings[0];
  2129. }
  2130. __finally
  2131. {
  2132. delete FileList1;
  2133. }
  2134. switch (ExecuteFileBy)
  2135. {
  2136. case efShell:
  2137. Counter = "RemoteFilesExecuted";
  2138. break;
  2139. case efInternalEditor:
  2140. Counter = "RemoteFilesOpenedInInternalEditor";
  2141. break;
  2142. case efExternalEditor:
  2143. Counter = "RemoteFilesOpenedInExternalEditor";
  2144. break;
  2145. default:
  2146. assert(false);
  2147. }
  2148. }
  2149. else
  2150. {
  2151. LocalFileName = FullFileName;
  2152. OriginalFileName = ExtractFileName(FullFileName);
  2153. switch (ExecuteFileBy)
  2154. {
  2155. case efShell:
  2156. Counter = "LocalFilesExecuted";
  2157. break;
  2158. case efInternalEditor:
  2159. Counter = "LocalFilesOpenedInInternalEditor";
  2160. break;
  2161. case efExternalEditor:
  2162. Counter = "LocalFilesOpenedInExternalEditor";
  2163. break;
  2164. default:
  2165. assert(false);
  2166. }
  2167. }
  2168. Configuration->Usage->Inc(Counter);
  2169. CustomExecuteFile(Side, ExecuteFileBy, LocalFileName, OriginalFileName,
  2170. ExternalEditor, LocalRootDirectory, RemoteDirectory);
  2171. }
  2172. //---------------------------------------------------------------------------
  2173. void __fastcall TCustomScpExplorerForm::ExecuteFile(TOperationSide Side,
  2174. TExecuteFileBy ExecuteFileBy, const TEditorData * ExternalEditor,
  2175. bool AllSelected, bool OnFocused)
  2176. {
  2177. assert(!WinConfiguration->DisableOpenEdit);
  2178. assert((ExecuteFileBy == efExternalEditor) ==
  2179. ((ExternalEditor != NULL) && (ExternalEditor->Editor == edExternal)));
  2180. Side = GetSide(Side);
  2181. TCustomDirView * DView = DirView(Side);
  2182. TStrings * FileList = AllSelected ?
  2183. DView->CreateFileList(OnFocused, Side == osLocal) :
  2184. DView->CreateFocusedFileList(Side == osLocal);
  2185. try
  2186. {
  2187. assert(AllSelected || (FileList->Count == 1));
  2188. for (int i = 0; i < FileList->Count; i++)
  2189. {
  2190. UnicodeString ListFileName = FileList->Strings[i];
  2191. UnicodeString FileNameOnly = (Side == osRemote) ?
  2192. UnixExtractFileName(ListFileName) : ExtractFileName(ListFileName);
  2193. TListItem * Item = DView->FindFileItem(FileNameOnly);
  2194. if (!DView->ItemIsDirectory(Item))
  2195. {
  2196. UnicodeString FullFileName;
  2197. if (Side == osRemote)
  2198. {
  2199. FullFileName = RemoteDirView->Path + ListFileName;
  2200. }
  2201. else
  2202. {
  2203. FullFileName = ListFileName;
  2204. }
  2205. TFileMasks::TParams MaskParams;
  2206. MaskParams.Size = DView->ItemFileSize(Item);
  2207. TDateTimePrecision Precision;
  2208. MaskParams.Modification = DView->ItemFileTime(Item, Precision);
  2209. ExecuteFile(Side, ExecuteFileBy, ExternalEditor, FullFileName,
  2210. FileList->Objects[i], MaskParams);
  2211. }
  2212. }
  2213. }
  2214. __finally
  2215. {
  2216. delete FileList;
  2217. }
  2218. }
  2219. //---------------------------------------------------------------------------
  2220. void __fastcall TCustomScpExplorerForm::ExecutedFileChanged(const UnicodeString FileName,
  2221. const TEditedFileData & Data, HANDLE UploadCompleteEvent)
  2222. {
  2223. if ((Data.Terminal == NULL) || !Data.Terminal->Active)
  2224. {
  2225. throw Exception(FMTLOAD(EDIT_SESSION_CLOSED,
  2226. (ExtractFileName(FileName), Data.SessionName)));
  2227. }
  2228. TStrings * FileList = new TStringList();
  2229. try
  2230. {
  2231. FileList->Add(FileName);
  2232. // consider using the same settings (preset) as when the file was downloaded
  2233. TGUICopyParamType CopyParam = GUIConfiguration->CurrentCopyParam;
  2234. if (Data.ForceText)
  2235. {
  2236. CopyParam.TransferMode = tmAscii;
  2237. }
  2238. // do not forget to add additional options to TemporarilyDownloadFiles, FAR and SS
  2239. CopyParam.FileNameCase = ncNoChange;
  2240. CopyParam.PreserveRights = false;
  2241. // so i do not need to worry if masking algorithm works in all cases
  2242. // ("" means "copy file name", no masking is actually done)
  2243. if (ExtractFileName(FileName) == Data.OriginalFileName)
  2244. {
  2245. CopyParam.FileMask = L"";
  2246. }
  2247. else
  2248. {
  2249. CopyParam.FileMask = DelimitFileNameMask(Data.OriginalFileName);
  2250. }
  2251. CopyParam.ReplaceInvalidChars = true;
  2252. CopyParam.IncludeFileMask = TFileMasks();
  2253. assert(Queue != NULL);
  2254. int Params = cpNoConfirmation | cpTemporary;
  2255. TQueueItem * QueueItem = new TUploadQueueItem(Data.Terminal, FileList,
  2256. Data.RemoteDirectory, &CopyParam, Params);
  2257. QueueItem->CompleteEvent = UploadCompleteEvent;
  2258. Data.Queue->AddItem(QueueItem);
  2259. }
  2260. __finally
  2261. {
  2262. delete FileList;
  2263. }
  2264. }
  2265. //---------------------------------------------------------------------------
  2266. void __fastcall TCustomScpExplorerForm::ExecutedFileReload(
  2267. const UnicodeString FileName, const TEditedFileData & Data)
  2268. {
  2269. if ((Data.Terminal == NULL) || !Data.Terminal->Active)
  2270. {
  2271. throw Exception(FMTLOAD(EDIT_SESSION_CLOSED_RELOAD,
  2272. (ExtractFileName(FileName), Data.SessionName)));
  2273. }
  2274. TRemoteFile * File = NULL;
  2275. TStrings * FileList = new TStringList();
  2276. try
  2277. {
  2278. UnicodeString RemoteFileName =
  2279. UnixIncludeTrailingBackslash(Data.RemoteDirectory) + Data.OriginalFileName;
  2280. FTerminal->ExceptionOnFail = true;
  2281. try
  2282. {
  2283. FTerminal->ReadFile(RemoteFileName, File);
  2284. if (!File->HaveFullFileName)
  2285. {
  2286. File->FullFileName = RemoteFileName;
  2287. }
  2288. }
  2289. __finally
  2290. {
  2291. FTerminal->ExceptionOnFail = false;
  2292. }
  2293. FileList->AddObject(RemoteFileName, File);
  2294. UnicodeString RootTempDir = Data.LocalRootDirectory;
  2295. UnicodeString TempDir = ExtractFilePath(FileName);
  2296. TTerminal * PrevTerminal = TTerminalManager::Instance()->ActiveTerminal;
  2297. TTerminalManager::Instance()->ActiveTerminal = Data.Terminal;
  2298. try
  2299. {
  2300. TemporarilyDownloadFiles(FileList, Data.ForceText, RootTempDir,
  2301. TempDir, true, true, true);
  2302. }
  2303. __finally
  2304. {
  2305. // it actually may not exist anymore...
  2306. TTerminalManager::Instance()->ActiveTerminal = PrevTerminal;
  2307. }
  2308. // sanity check, the target file name should be still the same
  2309. assert(ExtractFileName(FileName) == FileList->Strings[0]);
  2310. }
  2311. __finally
  2312. {
  2313. delete File;
  2314. delete FileList;
  2315. }
  2316. }
  2317. //---------------------------------------------------------------------------
  2318. void __fastcall TCustomScpExplorerForm::ExecutedFileEarlyClosed(
  2319. const TEditedFileData & Data, bool & KeepOpen)
  2320. {
  2321. // Command is set for external editors only (not for "shell" open).
  2322. if (!Data.Command.IsEmpty())
  2323. {
  2324. bool AnyFound = false;
  2325. bool AnyMDI = false;
  2326. bool AnyNonMDI = false;
  2327. bool AnyDetect = false;
  2328. TEditorList * EditorList = new TEditorList();
  2329. try
  2330. {
  2331. *EditorList = *WinConfiguration->EditorList;
  2332. for (int i = 0; i < EditorList->Count; i++)
  2333. {
  2334. const TEditorPreferences * Editor = EditorList->Editors[i];
  2335. if ((Editor->Data->Editor == edExternal) &&
  2336. (Editor->Data->ExternalEditor == Data.Command))
  2337. {
  2338. AnyFound = true;
  2339. if (Editor->Data->SDIExternalEditor)
  2340. {
  2341. AnyNonMDI = true;
  2342. if (Editor->Data->DetectMDIExternalEditor)
  2343. {
  2344. AnyDetect = true;
  2345. }
  2346. }
  2347. else
  2348. {
  2349. AnyMDI = true;
  2350. }
  2351. }
  2352. }
  2353. bool EnableMDI = false;
  2354. bool DisableDetect = false;
  2355. if (AnyMDI)
  2356. {
  2357. KeepOpen = true;
  2358. if (AnyNonMDI)
  2359. {
  2360. // there is at least one instance of the editor with MDI support enabled,
  2361. // and one with disabled, enable it for all instances
  2362. EnableMDI = true;
  2363. }
  2364. }
  2365. else if (AnyFound && !AnyDetect)
  2366. {
  2367. // at least once instance found but all have MDI autodetection disabled
  2368. // => close the file (default action)
  2369. }
  2370. else
  2371. {
  2372. // no instance of the editor has MDI support enabled
  2373. TMessageParams Params;
  2374. if (AnyFound)
  2375. {
  2376. // there is at least one instance of the editor
  2377. Params.Params |= mpNeverAskAgainCheck;
  2378. }
  2379. unsigned int Answer = MessageDialog(FMTLOAD(EDITOR_EARLY_CLOSED2, (Data.OriginalFileName)), qtWarning,
  2380. qaYes | qaNo, HELP_EDITOR_EARLY_CLOSED, &Params);
  2381. switch (Answer)
  2382. {
  2383. case qaNeverAskAgain:
  2384. DisableDetect = true;
  2385. break;
  2386. case qaNo:
  2387. EnableMDI = true;
  2388. KeepOpen = true;
  2389. break;
  2390. }
  2391. }
  2392. if (AnyFound && (EnableMDI || DisableDetect))
  2393. {
  2394. bool Changed = false;
  2395. for (int i = 0; i < EditorList->Count; i++)
  2396. {
  2397. const TEditorPreferences * Editor = EditorList->Editors[i];
  2398. if ((Editor->Data->Editor == edExternal) &&
  2399. (Editor->Data->ExternalEditor == Data.Command) &&
  2400. ((EnableMDI && Editor->Data->SDIExternalEditor) ||
  2401. (DisableDetect && Editor->Data->DetectMDIExternalEditor)))
  2402. {
  2403. Changed = true;
  2404. TEditorPreferences * UpdatedEditor = new TEditorPreferences(*Editor);
  2405. if (EnableMDI)
  2406. {
  2407. UpdatedEditor->GetData()->SDIExternalEditor = false;
  2408. }
  2409. if (DisableDetect)
  2410. {
  2411. UpdatedEditor->GetData()->DetectMDIExternalEditor = false;
  2412. }
  2413. EditorList->Change(i, UpdatedEditor);
  2414. }
  2415. }
  2416. if (Changed)
  2417. {
  2418. WinConfiguration->EditorList = EditorList;
  2419. }
  2420. }
  2421. }
  2422. __finally
  2423. {
  2424. delete EditorList;
  2425. }
  2426. }
  2427. else
  2428. {
  2429. // "open" case
  2430. MessageDialog(FMTLOAD(APP_EARLY_CLOSED, (Data.OriginalFileName)), qtWarning,
  2431. qaOK, HELP_APP_EARLY_CLOSED);
  2432. }
  2433. }
  2434. //---------------------------------------------------------------------------
  2435. void __fastcall TCustomScpExplorerForm::RemoteDirViewEnter(TObject * /*Sender*/)
  2436. {
  2437. SideEnter(osRemote);
  2438. }
  2439. //---------------------------------------------------------------------------
  2440. void __fastcall TCustomScpExplorerForm::RemoteDriveViewEnter(TObject * /*Sender*/)
  2441. {
  2442. MakeNextInTabOrder(RemoteDirView, RemoteDriveView);
  2443. SideEnter(osRemote);
  2444. }
  2445. //---------------------------------------------------------------------------
  2446. void __fastcall TCustomScpExplorerForm::SideEnter(TOperationSide Side)
  2447. {
  2448. FCurrentSide = Side;
  2449. if (Visible)
  2450. {
  2451. UpdateControls();
  2452. }
  2453. }
  2454. //---------------------------------------------------------------------------
  2455. void __fastcall TCustomScpExplorerForm::DeleteFiles(TOperationSide Side,
  2456. TStrings * FileList, bool Alternative)
  2457. {
  2458. assert(Terminal);
  2459. TCustomDirView * DView = DirView(Side);
  2460. DView->SaveSelection();
  2461. DView->SaveSelectedNames();
  2462. assert(!FAlternativeDelete);
  2463. FAlternativeDelete = Alternative;
  2464. try
  2465. {
  2466. if (Side == osRemote)
  2467. {
  2468. Terminal->DeleteFiles(FileList, FLAGMASK(Alternative, dfAlternative));
  2469. }
  2470. else
  2471. {
  2472. try
  2473. {
  2474. Terminal->DeleteLocalFiles(FileList, FLAGMASK(Alternative, dfAlternative));
  2475. }
  2476. __finally
  2477. {
  2478. ReloadLocalDirectory();
  2479. }
  2480. }
  2481. FAlternativeDelete = false;
  2482. }
  2483. catch(...)
  2484. {
  2485. FAlternativeDelete = false;
  2486. DView->DiscardSavedSelection();
  2487. throw;
  2488. }
  2489. DView->RestoreSelection();
  2490. }
  2491. //---------------------------------------------------------------------------
  2492. bool __fastcall TCustomScpExplorerForm::RemoteTransferDialog(TTerminal *& Session,
  2493. UnicodeString & Target, UnicodeString & FileMask, bool & DirectCopy,
  2494. bool NoConfirmation, bool Move)
  2495. {
  2496. if (RemoteDriveView->DropTarget != NULL)
  2497. {
  2498. Target = RemoteDriveView->NodePathName(RemoteDriveView->DropTarget);
  2499. }
  2500. else if (RemoteDirView->DropTarget != NULL)
  2501. {
  2502. assert(RemoteDirView->ItemIsDirectory(RemoteDirView->DropTarget));
  2503. Target = RemoteDirView->ItemFullFileName(RemoteDirView->DropTarget);
  2504. }
  2505. else
  2506. {
  2507. Target = RemoteDirView->Path;
  2508. }
  2509. if (Session == NULL)
  2510. {
  2511. Session = TTerminalManager::Instance()->ActiveTerminal;
  2512. }
  2513. Target = UnixIncludeTrailingBackslash(Target);
  2514. FileMask = L"*.*";
  2515. DirectCopy = FTerminal->IsCapable[fcRemoteCopy] || FTerminal->IsCapable[fcSecondaryShell];
  2516. bool Result = true;
  2517. if (!NoConfirmation)
  2518. {
  2519. if (Move)
  2520. {
  2521. Result = DoRemoteMoveDialog(Target, FileMask);
  2522. }
  2523. else
  2524. {
  2525. assert(Terminal != NULL);
  2526. // update Terminal->RemoteDirectory
  2527. UpdateTerminal(Terminal);
  2528. TStrings * Sessions = TTerminalManager::Instance()->TerminalList;
  2529. TStrings * Directories = new TStringList;
  2530. try
  2531. {
  2532. for (int Index = 0; Index < Sessions->Count; Index++)
  2533. {
  2534. TManagedTerminal * Terminal =
  2535. dynamic_cast<TManagedTerminal *>(Sessions->Objects[Index]);
  2536. Directories->Add(Terminal->RemoteDirectory);
  2537. }
  2538. TDirectRemoteCopy AllowDirectCopy;
  2539. if (FTerminal->IsCapable[fcRemoteCopy] || FTerminal->CommandSessionOpened)
  2540. {
  2541. assert(DirectCopy);
  2542. AllowDirectCopy = drcAllow;
  2543. }
  2544. else if (FTerminal->IsCapable[fcSecondaryShell])
  2545. {
  2546. assert(DirectCopy);
  2547. AllowDirectCopy = drcConfirmCommandSession;
  2548. }
  2549. else
  2550. {
  2551. assert(!DirectCopy);
  2552. AllowDirectCopy = drcDisallow;
  2553. }
  2554. void * ASession = Session;
  2555. Result = DoRemoteCopyDialog(Sessions, Directories, AllowDirectCopy,
  2556. ASession, Target, FileMask, DirectCopy);
  2557. Session = static_cast<TTerminal *>(ASession);
  2558. }
  2559. __finally
  2560. {
  2561. delete Directories;
  2562. }
  2563. }
  2564. }
  2565. return Result;
  2566. }
  2567. //---------------------------------------------------------------------------
  2568. bool __fastcall TCustomScpExplorerForm::RemoteTransferFiles(
  2569. TStrings * FileList, bool NoConfirmation, bool Move, TTerminal * Session)
  2570. {
  2571. bool DirectCopy;
  2572. UnicodeString Target, FileMask;
  2573. bool Result = RemoteTransferDialog(Session, Target, FileMask, DirectCopy, NoConfirmation, Move);
  2574. if (Result)
  2575. {
  2576. if (!Move && !DirectCopy)
  2577. {
  2578. UnicodeString RootTempDir;
  2579. UnicodeString TempDir;
  2580. TemporarilyDownloadFiles(FileList, false, RootTempDir, TempDir, false, false, false);
  2581. TStrings * TemporaryFilesList = new TStringList();
  2582. try
  2583. {
  2584. TMakeLocalFileListParams MakeFileListParam;
  2585. MakeFileListParam.FileList = TemporaryFilesList;
  2586. MakeFileListParam.IncludeDirs = true;
  2587. MakeFileListParam.Recursive = false;
  2588. ProcessLocalDirectory(TempDir, FTerminal->MakeLocalFileList, &MakeFileListParam);
  2589. TTerminalManager::Instance()->ActiveTerminal = Session;
  2590. TGUICopyParamType CopyParam = GUIConfiguration->CurrentCopyParam;
  2591. CopyParam.FileMask = FileMask;
  2592. assert(!FAutoOperation);
  2593. FAutoOperation = true;
  2594. FTerminal->CopyToRemote(TemporaryFilesList, Target, &CopyParam, cpTemporary);
  2595. }
  2596. __finally
  2597. {
  2598. delete TemporaryFilesList;
  2599. FAutoOperation = false;
  2600. RecursiveDeleteFile(ExcludeTrailingBackslash(RootTempDir), false);
  2601. }
  2602. }
  2603. else
  2604. {
  2605. RemoteDirView->SaveSelection();
  2606. RemoteDirView->SaveSelectedNames();
  2607. try
  2608. {
  2609. if (Move)
  2610. {
  2611. Terminal->MoveFiles(FileList, Target, FileMask);
  2612. }
  2613. else
  2614. {
  2615. assert(DirectCopy);
  2616. assert(Session == FTerminal);
  2617. if (FTerminal->IsCapable[fcRemoteCopy] ||
  2618. FTerminal->CommandSessionOpened ||
  2619. CommandSessionFallback())
  2620. {
  2621. Terminal->CopyFiles(FileList, Target, FileMask);
  2622. }
  2623. }
  2624. }
  2625. catch(...)
  2626. {
  2627. RemoteDirView->DiscardSavedSelection();
  2628. throw;
  2629. }
  2630. RemoteDirView->RestoreSelection();
  2631. }
  2632. }
  2633. return Result;
  2634. }
  2635. //---------------------------------------------------------------------------
  2636. void __fastcall TCustomScpExplorerForm::CreateDirectory(TOperationSide Side)
  2637. {
  2638. Side = GetSide(Side);
  2639. TRemoteProperties Properties = GUIConfiguration->NewDirectoryProperties;
  2640. TRemoteProperties * AProperties = (Side == osRemote ? &Properties : NULL);
  2641. UnicodeString Name = LoadStr(NEW_FOLDER);
  2642. bool SaveSettings = false;
  2643. if (DoCreateDirectoryDialog(Name, AProperties, SaveSettings))
  2644. {
  2645. if (Side == osRemote)
  2646. {
  2647. if (SaveSettings)
  2648. {
  2649. GUIConfiguration->NewDirectoryProperties = Properties;
  2650. }
  2651. RemoteDirView->CreateDirectoryEx(Name, &Properties);
  2652. }
  2653. else
  2654. {
  2655. DirView(Side)->CreateDirectory(Name);
  2656. }
  2657. }
  2658. }
  2659. //---------------------------------------------------------------------------
  2660. void __fastcall TCustomScpExplorerForm::HomeDirectory(TOperationSide Side)
  2661. {
  2662. DirView(Side)->ExecuteHomeDirectory();
  2663. }
  2664. //---------------------------------------------------------------------------
  2665. void __fastcall TCustomScpExplorerForm::OpenDirectory(TOperationSide Side)
  2666. {
  2667. DoOpenDirectoryDialog(odBrowse, Side);
  2668. }
  2669. //---------------------------------------------------------------------------
  2670. bool __fastcall TCustomScpExplorerForm::OpenBookmark(UnicodeString Local, UnicodeString Remote)
  2671. {
  2672. UnicodeString Path;
  2673. if (FCurrentSide == osRemote)
  2674. {
  2675. Path = Remote;
  2676. }
  2677. else
  2678. {
  2679. Path = Local;
  2680. }
  2681. bool Result = !Path.IsEmpty();
  2682. if (Result)
  2683. {
  2684. DirView(FCurrentSide)->Path = Path;
  2685. }
  2686. return Result;
  2687. }
  2688. //---------------------------------------------------------------------------
  2689. void __fastcall TCustomScpExplorerForm::RemoteDirViewGetSelectFilter(
  2690. TCustomDirView *Sender, bool Select, TFileFilter &Filter)
  2691. {
  2692. assert(Sender);
  2693. if (!DoSelectMaskDialog(Sender, Select, &Filter, Configuration)) Abort();
  2694. }
  2695. //---------------------------------------------------------------------------
  2696. void __fastcall TCustomScpExplorerForm::CalculateSize(
  2697. TStrings * FileList, __int64 & Size, TCalculateSizeStats & Stats,
  2698. bool & Close)
  2699. {
  2700. // terminal can be already closed (e.g. dropped connection)
  2701. if (Terminal != NULL)
  2702. {
  2703. try
  2704. {
  2705. Terminal->CalculateFilesSize(FileList, Size, 0, NULL, &Stats);
  2706. }
  2707. catch(...)
  2708. {
  2709. if (!Terminal->Active)
  2710. {
  2711. Close = true;
  2712. }
  2713. throw;
  2714. }
  2715. }
  2716. }
  2717. //---------------------------------------------------------------------------
  2718. void __fastcall TCustomScpExplorerForm::CalculateChecksum(const UnicodeString & Alg,
  2719. TStrings * FileList, TCalculatedChecksumEvent OnCalculatedChecksum,
  2720. bool & Close)
  2721. {
  2722. // terminal can be already closed (e.g. dropped connection)
  2723. if (Terminal != NULL)
  2724. {
  2725. Configuration->Usage->Inc(L"ChecksumCalculated");
  2726. try
  2727. {
  2728. Terminal->CalculateFilesChecksum(Alg, FileList, NULL, OnCalculatedChecksum);
  2729. }
  2730. catch(...)
  2731. {
  2732. if (!Terminal->Active)
  2733. {
  2734. Close = true;
  2735. }
  2736. throw;
  2737. }
  2738. }
  2739. }
  2740. //---------------------------------------------------------------------------
  2741. bool __fastcall TCustomScpExplorerForm::SetProperties(TOperationSide Side, TStrings * FileList)
  2742. {
  2743. bool Result;
  2744. if (Side == osRemote)
  2745. {
  2746. TRemoteTokenList * GroupList = NULL;
  2747. TRemoteTokenList * UserList = NULL;
  2748. try
  2749. {
  2750. TRemoteProperties CurrentProperties;
  2751. if (Terminal->LoadFilesProperties(FileList))
  2752. {
  2753. RemoteDirView->Invalidate();
  2754. }
  2755. bool CapableGroupChanging = Terminal->IsCapable[fcGroupChanging];
  2756. bool CapableOwnerChanging = Terminal->IsCapable[fcOwnerChanging];
  2757. if (CapableGroupChanging || CapableOwnerChanging)
  2758. {
  2759. if (CapableGroupChanging)
  2760. {
  2761. GroupList = Terminal->Groups->Duplicate();
  2762. }
  2763. if (CapableOwnerChanging)
  2764. {
  2765. UserList = Terminal->Users->Duplicate();
  2766. }
  2767. TRemoteDirectory * Files = Terminal->Files;
  2768. int Count = Files->Count;
  2769. if (Count > 100)
  2770. {
  2771. Count = 100;
  2772. }
  2773. for (int Index = 0; Index < Count; Index++)
  2774. {
  2775. TRemoteFile * File = Files->Files[Index];
  2776. if (CapableGroupChanging)
  2777. {
  2778. GroupList->AddUnique(File->Group);
  2779. }
  2780. if (CapableOwnerChanging)
  2781. {
  2782. UserList->AddUnique(File->Owner);
  2783. }
  2784. }
  2785. // if we haven't collected tokens for all files in current directory,
  2786. // make sure we collect them at least for all selected files.
  2787. // (note that so far the files in FileList has to be from current direcotry)
  2788. if (Count < Files->Count)
  2789. {
  2790. for (int Index = 0; Index < FileList->Count; Index++)
  2791. {
  2792. TRemoteFile * File = (TRemoteFile *)(FileList->Objects[Index]);
  2793. if (CapableGroupChanging)
  2794. {
  2795. GroupList->AddUnique(File->Group);
  2796. }
  2797. if (CapableOwnerChanging)
  2798. {
  2799. UserList->AddUnique(File->Owner);
  2800. }
  2801. }
  2802. }
  2803. }
  2804. CurrentProperties = TRemoteProperties::CommonProperties(FileList);
  2805. int Flags = 0;
  2806. if (Terminal->IsCapable[fcModeChanging]) Flags |= cpMode;
  2807. if (CapableOwnerChanging) Flags |= cpOwner;
  2808. if (CapableGroupChanging) Flags |= cpGroup;
  2809. TCalculateChecksumEvent CalculateChecksumEvent = NULL;
  2810. if (Terminal->IsCapable[fcCalculatingChecksum])
  2811. {
  2812. CalculateChecksumEvent = CalculateChecksum;
  2813. }
  2814. TRemoteProperties NewProperties = CurrentProperties;
  2815. Result =
  2816. DoPropertiesDialog(FileList, RemoteDirView->PathName,
  2817. GroupList, UserList, &NewProperties, Flags,
  2818. Terminal->IsCapable[fcGroupOwnerChangingByID],
  2819. CalculateSize, CalculateChecksumEvent);
  2820. if (Result)
  2821. {
  2822. NewProperties = TRemoteProperties::ChangedProperties(CurrentProperties, NewProperties);
  2823. Terminal->ChangeFilesProperties(FileList, &NewProperties);
  2824. }
  2825. }
  2826. __finally
  2827. {
  2828. delete GroupList;
  2829. delete UserList;
  2830. }
  2831. }
  2832. else
  2833. {
  2834. DirView(Side)->DisplayPropertiesMenu();
  2835. Result = true;
  2836. }
  2837. return Result;
  2838. }
  2839. //---------------------------------------------------------------------------
  2840. void __fastcall TCustomScpExplorerForm::KeyDown(Word & Key, Classes::TShiftState Shift)
  2841. {
  2842. if (QueueView2->Focused() && (QueueView2->OnKeyDown != NULL))
  2843. {
  2844. QueueView2->OnKeyDown(QueueView2, Key, Shift);
  2845. }
  2846. if (!DirView(osCurrent)->IsEditing())
  2847. {
  2848. TShortCut KeyShortCut = ShortCut(Key, Shift);
  2849. for (int Index = 0; Index < NonVisualDataModule->ExplorerActions->ActionCount; Index++)
  2850. {
  2851. TAction * Action = (TAction *)NonVisualDataModule->ExplorerActions->Actions[Index];
  2852. if (((Action->ShortCut == KeyShortCut) ||
  2853. (Action->SecondaryShortCuts->IndexOfShortCut(KeyShortCut) >= 0)) &&
  2854. AllowedAction(Action, aaShortCut))
  2855. {
  2856. Key = 0;
  2857. Action->Execute();
  2858. return;
  2859. }
  2860. }
  2861. for (int i = 0; i < TTerminalManager::Instance()->Count; i++)
  2862. {
  2863. if (NonVisualDataModule->OpenSessionShortCut(i) == KeyShortCut)
  2864. {
  2865. FIgnoreNextSysCommand = true;
  2866. TTerminalManager::Instance()->ActiveTerminalIndex = i;
  2867. return;
  2868. }
  2869. }
  2870. if (Key == VK_TAB && Shift.Contains(ssCtrl))
  2871. {
  2872. TTerminalManager::Instance()->CycleTerminals(!Shift.Contains(ssShift));
  2873. Key = 0;
  2874. }
  2875. if (IsCustomShortCut(KeyShortCut))
  2876. {
  2877. const TCustomCommandType * Command = WinConfiguration->CustomCommandList->Find(KeyShortCut);
  2878. if (Command != NULL)
  2879. {
  2880. if (CustomCommandState(*Command, false) > 0)
  2881. {
  2882. ExecuteFileOperationCommand(foCustomCommand, osRemote,
  2883. false, false, const_cast<TCustomCommandType *>(Command));
  2884. }
  2885. Key = 0;
  2886. }
  2887. if (WinConfiguration->SharedBookmarks != NULL)
  2888. {
  2889. TBookmark * Bookmark = WinConfiguration->SharedBookmarks->FindByShortCut(KeyShortCut);
  2890. if ((Bookmark != NULL) &&
  2891. OpenBookmark(Bookmark->Local, Bookmark->Remote))
  2892. {
  2893. Key = 0;
  2894. }
  2895. }
  2896. }
  2897. }
  2898. TForm::KeyDown(Key, Shift);
  2899. }
  2900. //---------------------------------------------------------------------------
  2901. void __fastcall TCustomScpExplorerForm::InitStatusBar()
  2902. {
  2903. const TSessionInfo & SessionInfo = Terminal->GetSessionInfo();
  2904. const TFileSystemInfo & FileSystemInfo = Terminal->GetFileSystemInfo();
  2905. TTBXStatusBar * SessionStatusBar = (TTBXStatusBar *)GetComponent(fcStatusBar);
  2906. assert(Terminal);
  2907. bool SecurityEnabled = !SessionInfo.SecurityProtocolName.IsEmpty();
  2908. SessionStatusBar->Panels->Items[1]->Enabled = SecurityEnabled;
  2909. // expanded from ?: to avoid memory leaks
  2910. if (SecurityEnabled)
  2911. {
  2912. SessionStatusBar->Panels->Items[1]->Hint =
  2913. FMTLOAD(STATUS_SECURE, (SessionInfo.SecurityProtocolName));
  2914. }
  2915. else
  2916. {
  2917. SessionStatusBar->Panels->Items[1]->Hint = LoadStr(STATUS_INSECURE);
  2918. }
  2919. if (FileSystemInfo.ProtocolName.IsEmpty())
  2920. {
  2921. SessionStatusBar->Panels->Items[2]->Caption = SessionInfo.ProtocolName;
  2922. }
  2923. else
  2924. {
  2925. SessionStatusBar->Panels->Items[2]->Caption = FileSystemInfo.ProtocolName;
  2926. }
  2927. SessionStatusBar->Panels->Items[2]->Hint = LoadStr(STATUS_PROTOCOL_HINT);
  2928. SessionStatusBar->Panels->Items[3]->Enabled =
  2929. (!SessionInfo.CSCompression.IsEmpty() || !SessionInfo.SCCompression.IsEmpty());
  2930. if (SessionInfo.CSCompression == SessionInfo.SCCompression)
  2931. {
  2932. SessionStatusBar->Panels->Items[3]->Hint =
  2933. FMTLOAD(STATUS_COMPRESSION_HINT, (DefaultStr(SessionInfo.CSCompression, LoadStr(NO_STR))));
  2934. }
  2935. else
  2936. {
  2937. SessionStatusBar->Panels->Items[3]->Hint = FMTLOAD(STATUS_COMPRESSION2_HINT,
  2938. (DefaultStr(SessionInfo.CSCompression, LoadStr(NO_STR)),
  2939. DefaultStr(SessionInfo.SCCompression, LoadStr(NO_STR))));
  2940. }
  2941. SessionStatusBar->Panels->Items[4]->Hint = LoadStr(STATUS_DURATION_HINT);
  2942. UpdateStatusBar();
  2943. }
  2944. //---------------------------------------------------------------------------
  2945. void __fastcall TCustomScpExplorerForm::UpdateStatusBar()
  2946. {
  2947. TTBXStatusBar * SessionStatusBar = (TTBXStatusBar *)GetComponent(fcStatusBar);
  2948. assert(SessionStatusBar != NULL);
  2949. if (FShowStatusBarHint)
  2950. {
  2951. SessionStatusBar->SimplePanel = true;
  2952. // escape hotkeys particularly because of the custom commands names
  2953. SessionStatusBar->SimpleText = EscapeHotkey(FStatusBarHint);
  2954. }
  2955. else if (!Terminal || !Terminal->Active || Terminal->Status < ssOpened)
  2956. {
  2957. // note: (Terminal->Status < sshReady) currently never happens here,
  2958. // so STATUS_CONNECTING is never used
  2959. SessionStatusBar->SimplePanel = true;
  2960. SessionStatusBar->SimpleText = LoadStr(
  2961. !Terminal || !Terminal->Active ? STATUS_DISCONNECTED : STATUS_CONNECTING);
  2962. }
  2963. else
  2964. {
  2965. assert(Terminal);
  2966. SessionStatusBar->SimplePanel = false;
  2967. const TSessionInfo & SessionInfo = Terminal->GetSessionInfo();
  2968. if (FNote.IsEmpty())
  2969. {
  2970. UpdateStatusPanelText(SessionStatusBar->Panels->Items[0]);
  2971. }
  2972. else
  2973. {
  2974. SessionStatusBar->Panels->Items[0]->Caption = FNote;
  2975. }
  2976. SessionStatusBar->Panels->Items[0]->Hint = FNoteHints;
  2977. SessionStatusBar->Panels->Items[4]->Caption =
  2978. FormatDateTimeSpan(Configuration->TimeFormat, Now() - SessionInfo.LoginTime);
  2979. }
  2980. }
  2981. //---------------------------------------------------------------------------
  2982. void __fastcall TCustomScpExplorerForm::UpdateStatusPanelText(TTBXStatusPanel * Panel)
  2983. {
  2984. Panel->Caption = L"";
  2985. }
  2986. //---------------------------------------------------------------------------
  2987. void __fastcall TCustomScpExplorerForm::Idle(bool AppIdle)
  2988. {
  2989. if (FShowing)
  2990. {
  2991. FEditorManager->Check();
  2992. // make sure that Idle is called before update queue, as it may invoke QueueEvent
  2993. // that needs to know if queue view is visible (and it may be closed after queue update)
  2994. TTerminalManager::Instance()->Idle();
  2995. if (AppIdle)
  2996. {
  2997. if (FRefreshRemoteDirectory)
  2998. {
  2999. if ((Terminal != NULL) && Terminal->Active)
  3000. {
  3001. Terminal->RefreshDirectory();
  3002. }
  3003. FRefreshRemoteDirectory = false;
  3004. }
  3005. if (FRefreshLocalDirectory)
  3006. {
  3007. ReloadLocalDirectory();
  3008. FRefreshLocalDirectory = false;
  3009. }
  3010. if (WinConfiguration->RefreshRemotePanel)
  3011. {
  3012. TManagedTerminal * ManagedTerminal =
  3013. dynamic_cast<TManagedTerminal *>(Terminal);
  3014. if ((ManagedTerminal != NULL) && Terminal->Active &&
  3015. (Now() - ManagedTerminal->DirectoryLoaded >
  3016. WinConfiguration->RefreshRemotePanelInterval))
  3017. {
  3018. RemoteDirView->ReloadDirectory();
  3019. }
  3020. }
  3021. }
  3022. if (FQueueStatusInvalidated)
  3023. {
  3024. UpdateQueueStatus(AppIdle, false);
  3025. }
  3026. RefreshQueueItems(AppIdle);
  3027. UpdateStatusBar();
  3028. }
  3029. FIgnoreNextSysCommand = false;
  3030. }
  3031. //---------------------------------------------------------------------------
  3032. void __fastcall TCustomScpExplorerForm::UserActionTimer(TObject * /*Sender*/)
  3033. {
  3034. try
  3035. {
  3036. FUserActionTimer->Enabled = false;
  3037. if (GUIConfiguration->QueueAutoPopup && (FPendingQueueActionItem != NULL))
  3038. {
  3039. if (TQueueItem::IsUserActionStatus(FPendingQueueActionItem->Status))
  3040. {
  3041. FPendingQueueActionItem->ProcessUserAction();
  3042. }
  3043. }
  3044. }
  3045. __finally
  3046. {
  3047. FPendingQueueActionItem = NULL;
  3048. }
  3049. }
  3050. //---------------------------------------------------------------------------
  3051. void __fastcall TCustomScpExplorerForm::ApplicationHint(TObject * /*Sender*/)
  3052. {
  3053. assert(Application);
  3054. UnicodeString AHint = GetLongHint(Application->Hint);
  3055. FShowStatusBarHint = Active && !AHint.IsEmpty();
  3056. if (FShowStatusBarHint)
  3057. {
  3058. FStatusBarHint = AHint != L"E" ? AHint : UnicodeString(L"");
  3059. }
  3060. else
  3061. {
  3062. FStatusBarHint = L"";
  3063. }
  3064. UpdateStatusBar();
  3065. }
  3066. //---------------------------------------------------------------------------
  3067. void __fastcall TCustomScpExplorerForm::ApplicationMinimize(TObject * /*Sender*/)
  3068. {
  3069. if (WinConfiguration->MinimizeToTray)
  3070. {
  3071. UpdateTrayIcon();
  3072. FTrayIcon->Visible = true;
  3073. ShowWindow(Handle, SW_HIDE);
  3074. }
  3075. }
  3076. //---------------------------------------------------------------------------
  3077. void __fastcall TCustomScpExplorerForm::ApplicationRestore(TObject * /*Sender*/)
  3078. {
  3079. if (FTrayIcon->Visible)
  3080. {
  3081. FTrayIcon->Visible = false;
  3082. ShowWindow(Handle, SW_SHOW);
  3083. }
  3084. }
  3085. //---------------------------------------------------------------------------
  3086. void __fastcall TCustomScpExplorerForm::UpdateTrayIcon()
  3087. {
  3088. FTrayIcon->Hint = Caption;
  3089. }
  3090. //---------------------------------------------------------------------------
  3091. void __fastcall TCustomScpExplorerForm::ApplicationTitleChanged()
  3092. {
  3093. UpdateTrayIcon();
  3094. }
  3095. //---------------------------------------------------------------------------
  3096. void __fastcall TCustomScpExplorerForm::TrayIconClick(TObject * /*Sender*/)
  3097. {
  3098. // workaround
  3099. // TApplication.WndProc sets TApplication.FAppIconic to false,
  3100. // on WM_ACTIVATEAPP, what renders TApplication.Restore no-op function.
  3101. // But WM_ACTIVATEAPP message can be received even when
  3102. // the main window is minimized to the tray and internal editor window is focused
  3103. // (after another application was previously active)
  3104. if (::IsIconic(Handle))
  3105. {
  3106. bool * AppIconic = reinterpret_cast<bool *>((reinterpret_cast<char *>(Application)) + 56);
  3107. if (!*AppIconic)
  3108. {
  3109. *AppIconic = true;
  3110. }
  3111. }
  3112. Application->Restore();
  3113. Application->BringToFront();
  3114. }
  3115. //---------------------------------------------------------------------------
  3116. bool __fastcall TCustomScpExplorerForm::OpenInNewWindow()
  3117. {
  3118. return FLAGSET(GetAsyncKeyState(VK_SHIFT), 0x8000);
  3119. }
  3120. //---------------------------------------------------------------------------
  3121. void __fastcall TCustomScpExplorerForm::NewSession()
  3122. {
  3123. if (OpenInNewWindow())
  3124. {
  3125. if (!ExecuteShell(Application->ExeName, L""))
  3126. {
  3127. throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Application->ExeName)));
  3128. }
  3129. }
  3130. else
  3131. {
  3132. TTerminalManager::Instance()->NewSession();
  3133. }
  3134. }
  3135. //---------------------------------------------------------------------------
  3136. void __fastcall TCustomScpExplorerForm::DuplicateSession()
  3137. {
  3138. TSessionData * SessionData = new TSessionData(L"");
  3139. try
  3140. {
  3141. SessionData->Assign(Terminal->SessionData);
  3142. // current working directories become defaults here, what is not right
  3143. UpdateSessionData(SessionData);
  3144. if (OpenInNewWindow())
  3145. {
  3146. UnicodeString SessionName = StoredSessions->HiddenPrefix + Terminal->SessionData->Name;
  3147. StoredSessions->NewSession(SessionName, SessionData);
  3148. // modified only, explicit
  3149. StoredSessions->Save(false, true);
  3150. if (!ExecuteShell(Application->ExeName, FORMAT(L"\"%s\"", (SessionName))))
  3151. {
  3152. throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Application->ExeName)));
  3153. }
  3154. }
  3155. else
  3156. {
  3157. TTerminalManager * Manager = TTerminalManager::Instance();
  3158. TTerminal * Terminal = Manager->NewTerminal(SessionData);
  3159. Manager->ActiveTerminal = Terminal;
  3160. Manager->ConnectActiveTerminal();
  3161. }
  3162. }
  3163. __finally
  3164. {
  3165. delete SessionData;
  3166. }
  3167. }
  3168. //---------------------------------------------------------------------------
  3169. bool __fastcall TCustomScpExplorerForm::CanCloseQueue()
  3170. {
  3171. assert(FQueue != NULL);
  3172. return (FQueue->IsEmpty ||
  3173. (MessageDialog(LoadStr(PENDING_QUEUE_ITEMS), qtWarning, qaOK | qaCancel, HELP_NONE) == qaOK));
  3174. }
  3175. //---------------------------------------------------------------------------
  3176. void __fastcall TCustomScpExplorerForm::CloseSession()
  3177. {
  3178. if (CanCloseQueue())
  3179. {
  3180. TTerminalManager::Instance()->FreeActiveTerminal();
  3181. }
  3182. }
  3183. //---------------------------------------------------------------------------
  3184. void __fastcall TCustomScpExplorerForm::OpenStoredSession(TSessionData * Data)
  3185. {
  3186. if (OpenInNewWindow())
  3187. {
  3188. // encode session name because of slashes in hierarchical sessions
  3189. if (!ExecuteShell(Application->ExeName, FORMAT(L"\"%s\"", (EncodeUrlChars(Data->Name)))))
  3190. {
  3191. throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Application->ExeName)));
  3192. }
  3193. }
  3194. else
  3195. {
  3196. TTerminalManager * Manager = TTerminalManager::Instance();
  3197. TTerminal * Terminal = Manager->NewTerminal(Data);
  3198. Manager->ActiveTerminal = Terminal;
  3199. Manager->ConnectActiveTerminal();
  3200. }
  3201. }
  3202. //---------------------------------------------------------------------------
  3203. void __fastcall TCustomScpExplorerForm::FormCloseQuery(TObject * /*Sender*/,
  3204. bool &CanClose)
  3205. {
  3206. if (Terminal->Active && WinConfiguration->ConfirmClosingSession)
  3207. {
  3208. unsigned int Result;
  3209. TMessageParams Params(mpNeverAskAgainCheck);
  3210. UnicodeString Message;
  3211. if (TTerminalManager::Instance()->Count > 1)
  3212. {
  3213. Message = LoadStr(CLOSE_SESSIONS);
  3214. }
  3215. else
  3216. {
  3217. Message = FMTLOAD(CLOSE_SESSION, (Terminal->SessionData->SessionName));
  3218. }
  3219. Result = MessageDialog(Message, qtConfirmation,
  3220. qaOK | qaCancel, HELP_NONE, &Params);
  3221. if (Result == qaNeverAskAgain)
  3222. {
  3223. WinConfiguration->ConfirmClosingSession = false;
  3224. }
  3225. CanClose = (Result == qaOK || Result == qaNeverAskAgain);
  3226. }
  3227. if (CanClose)
  3228. {
  3229. CanClose = CanCloseQueue();
  3230. }
  3231. if (CanClose)
  3232. {
  3233. CanClose =
  3234. FEditorManager->CloseInternalEditors(CloseInternalEditor) &&
  3235. FEditorManager->CloseExternalFilesWithoutProcess();
  3236. if (CanClose)
  3237. {
  3238. while (CanClose && (FLocalEditors->Count > 0))
  3239. {
  3240. int PrevCount = FLocalEditors->Count;
  3241. static_cast<TForm *>(FLocalEditors->Items[0])->Close();
  3242. CanClose = (FLocalEditors->Count < PrevCount);
  3243. }
  3244. if (CanClose)
  3245. {
  3246. CanClose =
  3247. FEditorManager->Empty(true) ||
  3248. (MessageDialog(LoadStr(PENDING_EDITORS), qtWarning, qaIgnore | qaCancel,
  3249. HELP_NONE) == qaIgnore);
  3250. }
  3251. }
  3252. }
  3253. }
  3254. //---------------------------------------------------------------------------
  3255. void __fastcall TCustomScpExplorerForm::CloseInternalEditor(TObject * Sender)
  3256. {
  3257. TForm * Form = dynamic_cast<TForm *>(Sender);
  3258. assert(Form != NULL);
  3259. Form->Close();
  3260. }
  3261. //---------------------------------------------------------------------------
  3262. void __fastcall TCustomScpExplorerForm::ForceCloseInternalEditor(TObject * Sender)
  3263. {
  3264. TForm * Form = dynamic_cast<TForm *>(Sender);
  3265. delete Form;
  3266. }
  3267. //---------------------------------------------------------------------------
  3268. void __fastcall TCustomScpExplorerForm::ForceCloseLocalEditors()
  3269. {
  3270. while (FLocalEditors->Count > 0)
  3271. {
  3272. delete static_cast<TForm *>(FLocalEditors->Items[0]);
  3273. }
  3274. }
  3275. //---------------------------------------------------------------------------
  3276. void __fastcall TCustomScpExplorerForm::RemoteDirViewDisplayProperties(
  3277. TObject *Sender)
  3278. {
  3279. APPLICATION_EXCEPTION_HACK_BEGIN
  3280. {
  3281. TStrings *FileList = ((TUnixDirView*)Sender)->CreateFileList(True, False, NULL);
  3282. try
  3283. {
  3284. SetProperties(osRemote, FileList);
  3285. }
  3286. __finally
  3287. {
  3288. delete FileList;
  3289. }
  3290. }
  3291. APPLICATION_EXCEPTION_HACK_END;
  3292. }
  3293. //---------------------------------------------------------------------------
  3294. void __fastcall TCustomScpExplorerForm::ComponentShowing(Byte Component, bool value)
  3295. {
  3296. if (value)
  3297. {
  3298. if (Component == fcCustomCommandsBand)
  3299. {
  3300. UpdateCustomCommandsToolbar();
  3301. }
  3302. }
  3303. }
  3304. //---------------------------------------------------------------------------
  3305. void __fastcall TCustomScpExplorerForm::SetComponentVisible(Byte Component, Boolean value)
  3306. {
  3307. TControl * Control = GetComponent(Component);
  3308. assert(Control);
  3309. bool Changed = (Control->Visible != value);
  3310. if (Changed)
  3311. {
  3312. ComponentShowing(Component, value);
  3313. TWinControl * WinControl = dynamic_cast<TWinControl*>(Control);
  3314. bool WasFocused = (WinControl != NULL) && (ActiveControl != NULL) &&
  3315. ((ActiveControl == WinControl) || (ActiveControl->Parent == WinControl));
  3316. if (value)
  3317. {
  3318. int RemainingHeight = Control->Parent->ClientHeight;
  3319. int RemainingWidth = Control->Parent->ClientWidth;
  3320. for (int i = 0; i < Control->Parent->ControlCount; i++)
  3321. {
  3322. TControl * ChildControl = Control->Parent->Controls[i];
  3323. if (ChildControl->Visible)
  3324. {
  3325. switch (ChildControl->Align)
  3326. {
  3327. case alTop:
  3328. case alBottom:
  3329. RemainingHeight -= ChildControl->Height;
  3330. break;
  3331. case alLeft:
  3332. case alRight:
  3333. RemainingWidth -= ChildControl->Width;
  3334. break;
  3335. }
  3336. }
  3337. }
  3338. static int Reserve = 32;
  3339. // queue in explorer, trees in commander
  3340. if (Control->Height > RemainingHeight - Reserve)
  3341. {
  3342. Control->Height = RemainingHeight / 2;
  3343. }
  3344. if (Control->Width > RemainingWidth - Reserve)
  3345. {
  3346. Control->Width = RemainingWidth / 2;
  3347. }
  3348. }
  3349. Control->Visible = value;
  3350. if (WasFocused && Visible)
  3351. {
  3352. DirView(osCurrent)->SetFocus();
  3353. }
  3354. FixControlsPlacement();
  3355. }
  3356. }
  3357. //---------------------------------------------------------------------------
  3358. bool __fastcall TCustomScpExplorerForm::GetComponentVisible(Byte Component)
  3359. {
  3360. TControl * Control = GetComponent(Component);
  3361. if (Control == NULL)
  3362. {
  3363. return false;
  3364. }
  3365. else
  3366. {
  3367. return Control->Visible;
  3368. }
  3369. }
  3370. //---------------------------------------------------------------------------
  3371. void __fastcall TCustomScpExplorerForm::FixControlsPlacement()
  3372. {
  3373. if (RemoteDirView->ItemFocused != NULL)
  3374. {
  3375. RemoteDirView->ItemFocused->MakeVisible(false);
  3376. }
  3377. QueueSplitter->Visible = QueuePanel->Visible;
  3378. RemotePanelSplitter->Visible = RemoteDriveView->Visible;
  3379. }
  3380. //---------------------------------------------------------------------------
  3381. TControl * __fastcall TCustomScpExplorerForm::GetComponent(Byte Component)
  3382. {
  3383. switch (Component) {
  3384. case fcStatusBar: return RemoteStatusBar;
  3385. case fcRemotePopup: return reinterpret_cast<TControl *>(NonVisualDataModule->RemoteFilePopup);
  3386. case fcQueueView: return QueuePanel;
  3387. case fcQueueToolbar: return QueueDock;
  3388. case fcRemoteTree: return RemoteDriveView;
  3389. case fcSessionsTabs: return SessionsPageControl;
  3390. default: return NULL;
  3391. }
  3392. }
  3393. //---------------------------------------------------------------------------
  3394. void __fastcall TCustomScpExplorerForm::DirViewColumnRightClick(
  3395. TObject *Sender, TListColumn *Column, TPoint &Point)
  3396. {
  3397. assert(NonVisualDataModule && Column && Sender);
  3398. NonVisualDataModule->ListColumn = Column;
  3399. TPoint ScreenPoint = ((TControl*)Sender)->ClientToScreen(Point);
  3400. TPopupMenu * DirViewColumnMenu;
  3401. if (Sender == RemoteDirView)
  3402. {
  3403. DirViewColumnMenu = NonVisualDataModule->RemoteDirViewColumnPopup;
  3404. NonVisualDataModule->RemoteSortByExtColumnPopupItem->Visible =
  3405. (Column->Index == uvName);
  3406. NonVisualDataModule->RemoteFormatSizeBytesPopupItem->Visible =
  3407. (Column->Index == uvSize);
  3408. }
  3409. else
  3410. {
  3411. DirViewColumnMenu = NonVisualDataModule->LocalDirViewColumnPopup;
  3412. NonVisualDataModule->LocalSortByExtColumnPopupItem->Visible =
  3413. (Column->Index == dvName);
  3414. NonVisualDataModule->LocalFormatSizeBytesPopupItem->Visible =
  3415. (Column->Index == dvSize);
  3416. }
  3417. DirViewColumnMenu->Popup(ScreenPoint.x, ScreenPoint.y);
  3418. }
  3419. //---------------------------------------------------------------------------
  3420. void __fastcall TCustomScpExplorerForm::DirViewExecFile(
  3421. TObject *Sender, TListItem *Item, bool &AllowExec)
  3422. {
  3423. DoDirViewExecFile(Sender, Item, AllowExec);
  3424. }
  3425. //---------------------------------------------------------------------------
  3426. void __fastcall TCustomScpExplorerForm::DoDirViewExecFile(TObject * Sender,
  3427. TListItem * Item, bool & AllowExec)
  3428. {
  3429. assert(Sender && Item && Configuration);
  3430. assert(AllowExec);
  3431. TCustomDirView * ADirView = (TCustomDirView *)Sender;
  3432. bool Remote = (ADirView == DirView(osRemote));
  3433. bool ResolvedSymlinks = !Remote || Terminal->ResolvingSymlinks;
  3434. // Anything special is done on double click only (not on "open" indicated by FForceExecution),
  3435. // on files only (not directories)
  3436. // and only when symlinks are resolved (apply to remote panel only)
  3437. if (!ADirView->ItemIsDirectory(Item) &&
  3438. (ResolvedSymlinks || FForceExecution))
  3439. {
  3440. if ((WinConfiguration->DoubleClickAction != dcaOpen) &&
  3441. !FForceExecution &&
  3442. ResolvedSymlinks)
  3443. {
  3444. if (WinConfiguration->DoubleClickAction == dcaCopy)
  3445. {
  3446. ExecuteFileOperation(foCopy,
  3447. (ADirView == DirView(osRemote) ? osRemote : osLocal),
  3448. true, !WinConfiguration->CopyOnDoubleClickConfirmation);
  3449. AllowExec = false;
  3450. }
  3451. else if (WinConfiguration->DoubleClickAction == dcaEdit)
  3452. {
  3453. if (!Remote || !WinConfiguration->DisableOpenEdit)
  3454. {
  3455. ExecuteFile(osCurrent, efDefaultEditor);
  3456. AllowExec = false;
  3457. }
  3458. }
  3459. else
  3460. {
  3461. assert(false);
  3462. }
  3463. }
  3464. // if we have not done anything special, fall back to default behaviour
  3465. if (AllowExec)
  3466. {
  3467. if (Remote && !WinConfiguration->DisableOpenEdit)
  3468. {
  3469. ExecuteFile(osRemote, efShell);
  3470. AllowExec = false;
  3471. }
  3472. }
  3473. }
  3474. }
  3475. //---------------------------------------------------------------------------
  3476. bool __fastcall TCustomScpExplorerForm::GetHasDirView(TOperationSide Side)
  3477. {
  3478. return ((Side == osRemote) || (Side == osCurrent));
  3479. }
  3480. //---------------------------------------------------------------------------
  3481. void __fastcall TCustomScpExplorerForm::CompareDirectories()
  3482. {
  3483. assert(false);
  3484. }
  3485. //---------------------------------------------------------------------------
  3486. void __fastcall TCustomScpExplorerForm::SynchronizeDirectories()
  3487. {
  3488. assert(false);
  3489. }
  3490. //---------------------------------------------------------------------------
  3491. bool __fastcall TCustomScpExplorerForm::DoSynchronizeDirectories(
  3492. UnicodeString & LocalDirectory, UnicodeString & RemoteDirectory, bool UseDefaults)
  3493. {
  3494. TSynchronizeParamType Params;
  3495. Params.LocalDirectory = LocalDirectory;
  3496. Params.RemoteDirectory = RemoteDirectory;
  3497. int UnusedParams =
  3498. (GUIConfiguration->SynchronizeParams &
  3499. (spPreviewChanges | spTimestamp | spNotByTime | spBySize));
  3500. Params.Params = GUIConfiguration->SynchronizeParams & ~UnusedParams;
  3501. Params.Options = GUIConfiguration->SynchronizeOptions;
  3502. bool SaveSettings = false;
  3503. TSynchronizeController Controller(&DoSynchronize, &DoSynchronizeInvalid,
  3504. &DoSynchronizeTooManyDirectories);
  3505. assert(FSynchronizeController == NULL);
  3506. FSynchronizeController = &Controller;
  3507. bool Result;
  3508. try
  3509. {
  3510. TCopyParamType CopyParam = GUIConfiguration->CurrentCopyParam;
  3511. int CopyParamAttrs = Terminal->UsableCopyParamAttrs(0).Upload;
  3512. int Options =
  3513. FLAGMASK(SynchronizeAllowSelectedOnly(), soAllowSelectedOnly);
  3514. Result = DoSynchronizeDialog(Params, &CopyParam, Controller.StartStop,
  3515. SaveSettings, Options, CopyParamAttrs, GetSynchronizeOptions, UseDefaults);
  3516. if (Result)
  3517. {
  3518. if (SaveSettings)
  3519. {
  3520. GUIConfiguration->SynchronizeParams = Params.Params | UnusedParams;
  3521. GUIConfiguration->SynchronizeOptions = Params.Options;
  3522. }
  3523. else
  3524. {
  3525. if (FLAGSET(GUIConfiguration->SynchronizeOptions, soSynchronizeAsk) &&
  3526. FLAGCLEAR(Params.Options, soSynchronizeAsk) &&
  3527. FLAGSET(Params.Options, soSynchronize))
  3528. {
  3529. GUIConfiguration->SynchronizeOptions =
  3530. (GUIConfiguration->SynchronizeOptions & ~soSynchronizeAsk) |
  3531. soSynchronize;
  3532. }
  3533. }
  3534. LocalDirectory = Params.LocalDirectory;
  3535. RemoteDirectory = Params.RemoteDirectory;
  3536. }
  3537. }
  3538. __finally
  3539. {
  3540. FSynchronizeController = NULL;
  3541. }
  3542. return Result;
  3543. }
  3544. //---------------------------------------------------------------------------
  3545. void __fastcall TCustomScpExplorerForm::DoSynchronize(
  3546. TSynchronizeController * /*Sender*/, const UnicodeString LocalDirectory,
  3547. const UnicodeString RemoteDirectory, const TCopyParamType & CopyParam,
  3548. const TSynchronizeParamType & Params, TSynchronizeChecklist ** Checklist,
  3549. TSynchronizeOptions * Options, bool Full)
  3550. {
  3551. if (Terminal->Status == ssOpened)
  3552. {
  3553. try
  3554. {
  3555. int PParams = Params.Params;
  3556. if (!Full)
  3557. {
  3558. PParams |= TTerminal::spNoRecurse | TTerminal::spUseCache |
  3559. TTerminal::spDelayProgress | TTerminal::spSubDirs;
  3560. }
  3561. else
  3562. {
  3563. // if keepuptodate is non-recursive,
  3564. // full sync before has to be non-recursive as well
  3565. if (FLAGCLEAR(Params.Options, soRecurse))
  3566. {
  3567. PParams |= TTerminal::spNoRecurse;
  3568. }
  3569. }
  3570. Synchronize(LocalDirectory, RemoteDirectory, smRemote, CopyParam,
  3571. PParams, Checklist, Options);
  3572. }
  3573. catch(Exception & E)
  3574. {
  3575. ShowExtendedExceptionEx(Terminal, &E);
  3576. throw;
  3577. }
  3578. }
  3579. }
  3580. //---------------------------------------------------------------------------
  3581. void __fastcall TCustomScpExplorerForm::DoSynchronizeInvalid(
  3582. TSynchronizeController * /*Sender*/, const UnicodeString Directory,
  3583. const UnicodeString ErrorStr)
  3584. {
  3585. if (!Directory.IsEmpty())
  3586. {
  3587. SimpleErrorDialog(FMTLOAD(WATCH_ERROR_DIRECTORY, (Directory)), ErrorStr);
  3588. }
  3589. else
  3590. {
  3591. SimpleErrorDialog(LoadStr(WATCH_ERROR_GENERAL), ErrorStr);
  3592. }
  3593. }
  3594. //---------------------------------------------------------------------------
  3595. void __fastcall TCustomScpExplorerForm::DoSynchronizeTooManyDirectories(
  3596. TSynchronizeController * /*Sender*/, int & MaxDirectories)
  3597. {
  3598. if (MaxDirectories < GUIConfiguration->MaxWatchDirectories)
  3599. {
  3600. MaxDirectories = GUIConfiguration->MaxWatchDirectories;
  3601. }
  3602. else
  3603. {
  3604. TMessageParams Params(mpNeverAskAgainCheck);
  3605. unsigned int Result = MessageDialog(
  3606. FMTLOAD(TOO_MANY_WATCH_DIRECTORIES, (MaxDirectories, MaxDirectories)),
  3607. qtConfirmation, qaYes | qaNo, HELP_TOO_MANY_WATCH_DIRECTORIES, &Params);
  3608. if ((Result == qaYes) || (Result == qaNeverAskAgain))
  3609. {
  3610. MaxDirectories *= 2;
  3611. if (Result == qaNeverAskAgain)
  3612. {
  3613. GUIConfiguration->MaxWatchDirectories = MaxDirectories;
  3614. }
  3615. }
  3616. else
  3617. {
  3618. Abort();
  3619. }
  3620. }
  3621. }
  3622. //---------------------------------------------------------------------------
  3623. void __fastcall TCustomScpExplorerForm::Synchronize(const UnicodeString LocalDirectory,
  3624. const UnicodeString RemoteDirectory, TSynchronizeMode Mode,
  3625. const TCopyParamType & CopyParam, int Params, TSynchronizeChecklist ** Checklist,
  3626. TSynchronizeOptions * Options)
  3627. {
  3628. assert(!FAutoOperation);
  3629. void * BatchStorage;
  3630. BatchStart(BatchStorage);
  3631. FAutoOperation = true;
  3632. TSynchronizeChecklist * AChecklist = NULL;
  3633. try
  3634. {
  3635. FSynchronizeProgressForm = new TSynchronizeProgressForm(Application, true, true);
  3636. if (FLAGCLEAR(Params, TTerminal::spDelayProgress))
  3637. {
  3638. FSynchronizeProgressForm->Start();
  3639. }
  3640. AChecklist = Terminal->SynchronizeCollect(LocalDirectory, RemoteDirectory,
  3641. static_cast<TTerminal::TSynchronizeMode>(Mode),
  3642. &CopyParam, Params | spNoConfirmation, TerminalSynchronizeDirectory,
  3643. Options);
  3644. SAFE_DESTROY(FSynchronizeProgressForm);
  3645. FSynchronizeProgressForm = new TSynchronizeProgressForm(Application, true, false);
  3646. if (FLAGCLEAR(Params, TTerminal::spDelayProgress))
  3647. {
  3648. FSynchronizeProgressForm->Start();
  3649. }
  3650. Terminal->SynchronizeApply(AChecklist, LocalDirectory, RemoteDirectory,
  3651. &CopyParam, Params | spNoConfirmation, TerminalSynchronizeDirectory);
  3652. }
  3653. __finally
  3654. {
  3655. if (Checklist == NULL)
  3656. {
  3657. delete AChecklist;
  3658. }
  3659. else
  3660. {
  3661. *Checklist = AChecklist;
  3662. }
  3663. FAutoOperation = false;
  3664. SAFE_DESTROY(FSynchronizeProgressForm);
  3665. BatchEnd(BatchStorage);
  3666. ReloadLocalDirectory();
  3667. }
  3668. }
  3669. //---------------------------------------------------------------------------
  3670. bool __fastcall TCustomScpExplorerForm::SynchronizeAllowSelectedOnly()
  3671. {
  3672. // can be called from command line
  3673. return Visible &&
  3674. ((DirView(osRemote)->SelCount > 0) ||
  3675. (HasDirView[osLocal] && (DirView(osLocal)->SelCount > 0)));
  3676. }
  3677. //---------------------------------------------------------------------------
  3678. void __fastcall TCustomScpExplorerForm::GetSynchronizeOptions(
  3679. int Params, TSynchronizeOptions & Options)
  3680. {
  3681. if (FLAGSET(Params, spSelectedOnly) && SynchronizeAllowSelectedOnly())
  3682. {
  3683. Options.Filter = new TStringList();
  3684. Options.Filter->CaseSensitive = false;
  3685. Options.Filter->Duplicates = dupAccept;
  3686. if (DirView(osRemote)->SelCount > 0)
  3687. {
  3688. DirView(osRemote)->CreateFileList(false, false, Options.Filter);
  3689. }
  3690. if (HasDirView[osLocal] && (DirView(osLocal)->SelCount > 0))
  3691. {
  3692. DirView(osLocal)->CreateFileList(false, false, Options.Filter);
  3693. }
  3694. Options.Filter->Sort();
  3695. }
  3696. }
  3697. //---------------------------------------------------------------------------
  3698. bool __fastcall TCustomScpExplorerForm::DoFullSynchronizeDirectories(
  3699. UnicodeString & LocalDirectory, UnicodeString & RemoteDirectory,
  3700. TSynchronizeMode & Mode, bool & SaveMode, bool UseDefaults)
  3701. {
  3702. bool Result;
  3703. int Params = GUIConfiguration->SynchronizeParams;
  3704. bool SaveSettings = false;
  3705. int Options =
  3706. FLAGMASK(!Terminal->IsCapable[fcTimestampChanging], fsoDisableTimestamp) |
  3707. FLAGMASK(SynchronizeAllowSelectedOnly(), fsoAllowSelectedOnly);
  3708. TCopyParamType CopyParam = GUIConfiguration->CurrentCopyParam;
  3709. TUsableCopyParamAttrs CopyParamAttrs = Terminal->UsableCopyParamAttrs(0);
  3710. Result = UseDefaults ||
  3711. DoFullSynchronizeDialog(Mode, Params, LocalDirectory, RemoteDirectory,
  3712. &CopyParam, SaveSettings, SaveMode, Options, CopyParamAttrs);
  3713. if (Result)
  3714. {
  3715. Configuration->Usage->Inc(L"Synchronizations");
  3716. UpdateCopyParamCounters(CopyParam);
  3717. TSynchronizeOptions SynchronizeOptions;
  3718. GetSynchronizeOptions(Params, SynchronizeOptions);
  3719. if (SaveSettings)
  3720. {
  3721. GUIConfiguration->SynchronizeParams = Params;
  3722. }
  3723. else
  3724. {
  3725. SaveMode = false;
  3726. }
  3727. TDateTime StartTime = Now();
  3728. TSynchronizeChecklist * Checklist = NULL;
  3729. try
  3730. {
  3731. assert(!FAutoOperation);
  3732. FAutoOperation = true;
  3733. try
  3734. {
  3735. FSynchronizeProgressForm = new TSynchronizeProgressForm(Application, true, true);
  3736. FSynchronizeProgressForm->Start();
  3737. Checklist = Terminal->SynchronizeCollect(LocalDirectory, RemoteDirectory,
  3738. static_cast<TTerminal::TSynchronizeMode>(Mode),
  3739. &CopyParam, Params | spNoConfirmation, TerminalSynchronizeDirectory,
  3740. &SynchronizeOptions);
  3741. }
  3742. __finally
  3743. {
  3744. FAutoOperation = false;
  3745. SAFE_DESTROY(FSynchronizeProgressForm);
  3746. }
  3747. if (Checklist->Count == 0)
  3748. {
  3749. MessageDialog(LoadStr(COMPARE_NO_DIFFERENCES), qtInformation, qaOK,
  3750. HELP_SYNCHRONIZE_NO_DIFFERENCES);
  3751. }
  3752. else if (FLAGCLEAR(Params, spPreviewChanges) ||
  3753. DoSynchronizeChecklistDialog(Checklist, Mode, Params,
  3754. LocalDirectory, RemoteDirectory, CustomCommandMenu))
  3755. {
  3756. assert(!FAutoOperation);
  3757. void * BatchStorage;
  3758. BatchStart(BatchStorage);
  3759. FAutoOperation = true;
  3760. if (FLAGSET(Params, spPreviewChanges))
  3761. {
  3762. StartTime = Now();
  3763. }
  3764. try
  3765. {
  3766. FSynchronizeProgressForm = new TSynchronizeProgressForm(Application, true, false);
  3767. FSynchronizeProgressForm->Start();
  3768. Terminal->SynchronizeApply(Checklist, LocalDirectory, RemoteDirectory,
  3769. &CopyParam, Params | spNoConfirmation, TerminalSynchronizeDirectory);
  3770. }
  3771. __finally
  3772. {
  3773. FAutoOperation = false;
  3774. SAFE_DESTROY(FSynchronizeProgressForm);
  3775. BatchEnd(BatchStorage);
  3776. ReloadLocalDirectory();
  3777. }
  3778. }
  3779. }
  3780. __finally
  3781. {
  3782. delete Checklist;
  3783. }
  3784. OperationComplete(StartTime);
  3785. }
  3786. return Result;
  3787. }
  3788. //---------------------------------------------------------------------------
  3789. void __fastcall TCustomScpExplorerForm::TerminalSynchronizeDirectory(
  3790. const UnicodeString LocalDirectory, const UnicodeString RemoteDirectory,
  3791. bool & Continue, bool /*Collect*/)
  3792. {
  3793. assert(FSynchronizeProgressForm != NULL);
  3794. if (!FSynchronizeProgressForm->Started)
  3795. {
  3796. FSynchronizeProgressForm->Start();
  3797. }
  3798. FSynchronizeProgressForm->SetData(LocalDirectory, RemoteDirectory, Continue);
  3799. }
  3800. //---------------------------------------------------------------------------
  3801. void __fastcall TCustomScpExplorerForm::ExploreLocalDirectory()
  3802. {
  3803. assert(false);
  3804. }
  3805. //---------------------------------------------------------------------------
  3806. void __fastcall TCustomScpExplorerForm::SaveCurrentSession()
  3807. {
  3808. TSessionData * SessionData = new TSessionData(L"");
  3809. try
  3810. {
  3811. SessionData->Assign(Terminal->SessionData);
  3812. UpdateSessionData(SessionData);
  3813. TSessionData * EditingSessionData = StoredSessions->FindSame(SessionData);
  3814. bool SavePassword;
  3815. bool * PSavePassword;
  3816. bool NotRecommendedSavingPassword =
  3817. !CustomWinConfiguration->UseMasterPassword &&
  3818. !SameText(SessionData->UserName, AnonymousUserName);
  3819. if (Configuration->DisablePasswordStoring ||
  3820. !SessionData->HasAnyPassword())
  3821. {
  3822. PSavePassword = NULL;
  3823. }
  3824. else
  3825. {
  3826. PSavePassword = &SavePassword;
  3827. SavePassword =
  3828. ((EditingSessionData != NULL) &&
  3829. (EditingSessionData->Password == SessionData->Password)) ||
  3830. !NotRecommendedSavingPassword;
  3831. }
  3832. UnicodeString SessionName = Terminal->SessionData->SessionName;
  3833. if (DoSaveSessionDialog(SessionName, PSavePassword, EditingSessionData, NotRecommendedSavingPassword))
  3834. {
  3835. if ((PSavePassword != NULL) && !*PSavePassword)
  3836. {
  3837. SessionData->Password = L"";
  3838. }
  3839. StoredSessions->NewSession(SessionName, SessionData);
  3840. // modified only, explicit
  3841. StoredSessions->Save(false, true);
  3842. }
  3843. }
  3844. __finally
  3845. {
  3846. delete SessionData;
  3847. }
  3848. }
  3849. //---------------------------------------------------------------------------
  3850. void __fastcall TCustomScpExplorerForm::UpdateTerminal(TTerminal * Terminal)
  3851. {
  3852. TManagedTerminal * ManagedTerminal = dynamic_cast<TManagedTerminal *>(FTerminal);
  3853. assert(ManagedTerminal != NULL);
  3854. SAFE_DESTROY(ManagedTerminal->RemoteExplorerState);
  3855. if (WinConfiguration->PreservePanelState)
  3856. {
  3857. ManagedTerminal->RemoteExplorerState = RemoteDirView->SaveState();
  3858. }
  3859. // cannot use RemoteDirView->Path, because it is empty if connection
  3860. // was already closed
  3861. // also only peek, we may not be connected at all atm,
  3862. // so make sure we do not try retrieving current directory from the server
  3863. // (particularly with FTP)
  3864. UnicodeString ACurrentDirectory = Terminal->PeekCurrentDirectory();
  3865. if (!ACurrentDirectory.IsEmpty())
  3866. {
  3867. ManagedTerminal->RemoteDirectory = ACurrentDirectory;
  3868. }
  3869. ManagedTerminal->Color = SessionColor;
  3870. }
  3871. //---------------------------------------------------------------------------
  3872. void __fastcall TCustomScpExplorerForm::UpdateSessionData(TSessionData * Data)
  3873. {
  3874. assert(Data != NULL);
  3875. // cannot use RemoteDirView->Path, because it is empty if connection
  3876. // was already closed
  3877. // also only peek, we may not be connected at all atm
  3878. // (well this can hardly be true here, as opposite to UpdateTerminal above),
  3879. // so make sure we do not try retrieving current directory from the server
  3880. // (particularly with FTP)
  3881. UnicodeString ACurrentDirectory = Terminal->PeekCurrentDirectory();
  3882. if (!ACurrentDirectory.IsEmpty())
  3883. {
  3884. Data->RemoteDirectory = ACurrentDirectory;
  3885. }
  3886. Data->Color = SessionColor;
  3887. }
  3888. //---------------------------------------------------------------------------
  3889. void __fastcall TCustomScpExplorerForm::ToolBarResize(TObject *Sender)
  3890. {
  3891. TTBXToolbar * Toolbar = dynamic_cast<TTBXToolbar*>(Sender);
  3892. assert(Toolbar != NULL);
  3893. for (int i = 0; i < Toolbar->Items->Count; i++)
  3894. {
  3895. TTBXCustomDropDownItem * DropDownItem;
  3896. DropDownItem = dynamic_cast<TTBXCustomDropDownItem *>(Toolbar->Items->Items[i]);
  3897. if (DropDownItem != NULL)
  3898. {
  3899. ToolbarItemResize(DropDownItem,
  3900. Toolbar->Width - (Toolbar->View->BaseSize.x - DropDownItem->EditWidth) -
  3901. Toolbar->NonClientWidth);
  3902. break;
  3903. }
  3904. }
  3905. }
  3906. //---------------------------------------------------------------------------
  3907. void __fastcall TCustomScpExplorerForm::ToolbarItemResize(TTBXCustomDropDownItem * Item, int Width)
  3908. {
  3909. Item->EditWidth = Width;
  3910. }
  3911. //---------------------------------------------------------------------------
  3912. void __fastcall TCustomScpExplorerForm::ToolbarGetBaseSize(
  3913. TTBCustomToolbar * Toolbar, TPoint & ASize)
  3914. {
  3915. for (int i = 0; i < Toolbar->Items->Count; i++)
  3916. {
  3917. TTBXCustomDropDownItem * DropDownItem;
  3918. DropDownItem = dynamic_cast<TTBXCustomDropDownItem *>(Toolbar->Items->Items[i]);
  3919. if (DropDownItem != NULL)
  3920. {
  3921. ASize.x -= DropDownItem->EditWidth;
  3922. ASize.x += 50 /* minimal combo width */;
  3923. }
  3924. }
  3925. }
  3926. //---------------------------------------------------------------------------
  3927. void __fastcall TCustomScpExplorerForm::DoWarnLackOfTempSpace(
  3928. const UnicodeString Path, __int64 RequiredSpace, bool & Continue)
  3929. {
  3930. if (WinConfiguration->DDWarnLackOfTempSpace)
  3931. {
  3932. UnicodeString ADrive = ExtractFileDrive(ExpandFileName(Path));
  3933. if (!ADrive.IsEmpty())
  3934. {
  3935. __int64 FreeSpace = DiskFree((Byte)(ADrive[1]-'A'+1));
  3936. assert(RequiredSpace >= 0);
  3937. __int64 RequiredWithReserve;
  3938. RequiredWithReserve = (__int64)(RequiredSpace * WinConfiguration->DDWarnLackOfTempSpaceRatio);
  3939. if (FreeSpace < RequiredWithReserve)
  3940. {
  3941. unsigned int Result;
  3942. TMessageParams Params(mpNeverAskAgainCheck);
  3943. Result = MessageDialog(FMTLOAD(DD_WARN_LACK_OF_TEMP_SPACE, (Path,
  3944. FormatBytes(FreeSpace), FormatBytes(RequiredSpace))),
  3945. qtWarning, qaYes | qaNo, HELP_DD_WARN_LACK_OF_TEMP_SPACE, &Params);
  3946. if (Result == qaNeverAskAgain)
  3947. {
  3948. WinConfiguration->DDWarnLackOfTempSpace = false;
  3949. }
  3950. Continue = (Result == qaYes || Result == qaNeverAskAgain);
  3951. }
  3952. }
  3953. }
  3954. }
  3955. //---------------------------------------------------------------------------
  3956. void __fastcall TCustomScpExplorerForm::AddBookmark(TOperationSide Side)
  3957. {
  3958. DoOpenDirectoryDialog(odAddBookmark, Side);
  3959. }
  3960. //---------------------------------------------------------------------------
  3961. TStrings * __fastcall TCustomScpExplorerForm::CreateVisitedDirectories(TOperationSide Side)
  3962. {
  3963. TStringList * VisitedDirectories = new TStringList();
  3964. try
  3965. {
  3966. TCustomDirView * DView = DirView(Side);
  3967. VisitedDirectories->Duplicates = dupIgnore;
  3968. // we should better use TCustomDirView::FCaseSensitive, but it is private
  3969. VisitedDirectories->CaseSensitive = (Side == osRemote);
  3970. VisitedDirectories->Sorted = true;
  3971. for (int Index = -DView->BackCount; Index <= DView->ForwardCount; Index++)
  3972. {
  3973. VisitedDirectories->Add(DView->HistoryPath[Index]);
  3974. }
  3975. }
  3976. catch (...)
  3977. {
  3978. delete VisitedDirectories;
  3979. throw;
  3980. }
  3981. return VisitedDirectories;
  3982. }
  3983. //---------------------------------------------------------------------------
  3984. void __fastcall TCustomScpExplorerForm::DoOpenDirectoryDialog(
  3985. TOpenDirectoryMode Mode, TOperationSide Side)
  3986. {
  3987. bool Continue = true;
  3988. if (Mode == odAddBookmark)
  3989. {
  3990. TMessageParams Params(mpNeverAskAgainCheck);
  3991. Params.NewerAskAgainTitle = LoadStr(ADD_BOOKMARK_SHARED);
  3992. Params.NewerAskAgainCheckedInitially = WinConfiguration->UseSharedBookmarks;
  3993. unsigned int Answer =
  3994. MessageDialog(FMTLOAD(ADD_BOOKMARK_CONFIRM, (DirView(Side)->PathName)),
  3995. qtConfirmation, qaYes | qaNo, HELP_ADD_BOOKMARK_CONFIRM, &Params);
  3996. if (Answer == qaNeverAskAgain)
  3997. {
  3998. Continue = true;
  3999. WinConfiguration->UseSharedBookmarks = true;
  4000. }
  4001. else if (Answer == qaYes)
  4002. {
  4003. Continue = true;
  4004. WinConfiguration->UseSharedBookmarks = false;
  4005. }
  4006. else
  4007. {
  4008. Continue = false;
  4009. }
  4010. }
  4011. if (Continue)
  4012. {
  4013. TStrings * VisitedDirectories = CreateVisitedDirectories(Side);
  4014. try
  4015. {
  4016. UnicodeString Name = DirView(Side)->PathName;
  4017. if (::DoOpenDirectoryDialog(Mode, Side, Name, VisitedDirectories, Terminal,
  4018. HasDirView[osLocal]))
  4019. {
  4020. DirView(Side)->Path = Name;
  4021. }
  4022. }
  4023. __finally
  4024. {
  4025. delete VisitedDirectories;
  4026. }
  4027. }
  4028. }
  4029. //---------------------------------------------------------------------------
  4030. bool __fastcall TCustomScpExplorerForm::CommandSessionFallback()
  4031. {
  4032. bool Result = true;
  4033. assert(!FTerminal->CommandSessionOpened);
  4034. try
  4035. {
  4036. TTerminalManager::ConnectTerminal(FTerminal->CommandSession, false);
  4037. }
  4038. catch(Exception & E)
  4039. {
  4040. ShowExtendedExceptionEx(FTerminal->CommandSession, &E);
  4041. Result = false;
  4042. }
  4043. return Result;
  4044. }
  4045. //---------------------------------------------------------------------------
  4046. bool __fastcall TCustomScpExplorerForm::EnsureCommandSessionFallback(TFSCapability Capability)
  4047. {
  4048. bool Result = FTerminal->IsCapable[Capability] ||
  4049. FTerminal->CommandSessionOpened;
  4050. if (!Result)
  4051. {
  4052. assert(FTerminal->IsCapable[fcSecondaryShell]);
  4053. if (!GUIConfiguration->ConfirmCommandSession)
  4054. {
  4055. Result = true;
  4056. }
  4057. else
  4058. {
  4059. TMessageParams Params(mpNeverAskAgainCheck);
  4060. const TFileSystemInfo & FileSystemInfo = Terminal->GetFileSystemInfo();
  4061. unsigned int Answer = MessageDialog(FMTLOAD(PERFORM_ON_COMMAND_SESSION,
  4062. (FileSystemInfo.ProtocolName, FileSystemInfo.ProtocolName)), qtConfirmation,
  4063. qaOK | qaCancel, HELP_PERFORM_ON_COMMAND_SESSION, &Params);
  4064. if (Answer == qaNeverAskAgain)
  4065. {
  4066. GUIConfiguration->ConfirmCommandSession = false;
  4067. Result = true;
  4068. }
  4069. else if (Answer == qaOK)
  4070. {
  4071. Result = true;
  4072. }
  4073. }
  4074. if (Result)
  4075. {
  4076. Result = CommandSessionFallback();
  4077. }
  4078. }
  4079. return Result;
  4080. }
  4081. //---------------------------------------------------------------------------
  4082. void __fastcall TCustomScpExplorerForm::OpenConsole(UnicodeString Command)
  4083. {
  4084. if (EnsureCommandSessionFallback(fcAnyCommand))
  4085. {
  4086. DoConsoleDialog(Terminal, Command);
  4087. }
  4088. }
  4089. //---------------------------------------------------------------------------
  4090. void __fastcall TCustomScpExplorerForm::FileControlDDDragEnter(
  4091. TObject *Sender, _di_IDataObject /*DataObj*/, int /*grfKeyState*/,
  4092. const TPoint & /*Point*/, int & /*dwEffect*/, bool & Accept)
  4093. {
  4094. if (IsFileControl(DropSourceControl, osRemote) &&
  4095. (FDDExtMapFile != NULL))
  4096. {
  4097. Accept = true;
  4098. }
  4099. FDDTargetControl = dynamic_cast<TControl*>(Sender);
  4100. assert(FDDTargetControl != NULL);
  4101. }
  4102. //---------------------------------------------------------------------------
  4103. void __fastcall TCustomScpExplorerForm::SessionsDDDragEnter(
  4104. _di_IDataObject DataObj, int KeyState,
  4105. const TPoint & Point, int & Effect, bool & Accept)
  4106. {
  4107. FileControlDDDragEnter(SessionsPageControl, DataObj, KeyState, Point, Effect, Accept);
  4108. }
  4109. //---------------------------------------------------------------------------
  4110. void __fastcall TCustomScpExplorerForm::FileControlDDDragLeave(
  4111. TObject * Sender)
  4112. {
  4113. USEDPARAM(Sender);
  4114. assert(FDDTargetControl == Sender);
  4115. FDDTargetControl = NULL;
  4116. }
  4117. //---------------------------------------------------------------------------
  4118. void __fastcall TCustomScpExplorerForm::SessionsDDDragLeave()
  4119. {
  4120. FileControlDDDragLeave(SessionsPageControl);
  4121. }
  4122. //---------------------------------------------------------------------------
  4123. void __fastcall TCustomScpExplorerForm::AddEditLink(bool Add)
  4124. {
  4125. assert(FCurrentSide == osRemote);
  4126. bool Edit = false;
  4127. TRemoteFile * File = NULL;
  4128. UnicodeString FileName;
  4129. UnicodeString PointTo;
  4130. bool SymbolicLink = true;
  4131. if (RemoteDirView->ItemFocused)
  4132. {
  4133. assert(RemoteDirView->ItemFocused->Data);
  4134. File = (TRemoteFile *)RemoteDirView->ItemFocused->Data;
  4135. Edit = !Add && File->IsSymLink && Terminal->SessionData->ResolveSymlinks;
  4136. if (Edit)
  4137. {
  4138. FileName = File->FileName;
  4139. PointTo = File->LinkTo;
  4140. }
  4141. else
  4142. {
  4143. PointTo = File->FileName;
  4144. }
  4145. }
  4146. if (DoSymlinkDialog(FileName, PointTo, osRemote, SymbolicLink, Edit,
  4147. Terminal->IsCapable[fcHardLink]))
  4148. {
  4149. Configuration->Usage->Inc(L"RemoteLinksCreated");
  4150. if (Edit)
  4151. {
  4152. assert(File->FileName == FileName);
  4153. int Params = dfNoRecursive;
  4154. Terminal->ExceptionOnFail = true;
  4155. try
  4156. {
  4157. Terminal->DeleteFile(L"", File, &Params);
  4158. }
  4159. __finally
  4160. {
  4161. Terminal->ExceptionOnFail = false;
  4162. }
  4163. }
  4164. Terminal->CreateLink(FileName, PointTo, SymbolicLink);
  4165. }
  4166. }
  4167. //---------------------------------------------------------------------------
  4168. bool __fastcall TCustomScpExplorerForm::CanAddEditLink()
  4169. {
  4170. return
  4171. (Terminal != NULL) &&
  4172. ((DirView(osCurrent) != DirView(osRemote)) ||
  4173. (Terminal->ResolvingSymlinks &&
  4174. Terminal->IsCapable[fcSymbolicLink]));
  4175. }
  4176. //---------------------------------------------------------------------------
  4177. bool __fastcall TCustomScpExplorerForm::LinkFocused()
  4178. {
  4179. return
  4180. (FCurrentSide == osRemote) &&
  4181. (RemoteDirView->ItemFocused != NULL) &&
  4182. ((TRemoteFile *)RemoteDirView->ItemFocused->Data)->IsSymLink &&
  4183. Terminal->SessionData->ResolveSymlinks;
  4184. }
  4185. //---------------------------------------------------------------------------
  4186. void __fastcall TCustomScpExplorerForm::ExecuteCurrentFile()
  4187. {
  4188. assert(!WinConfiguration->DisableOpenEdit);
  4189. FForceExecution = true;
  4190. try
  4191. {
  4192. DirView(osCurrent)->ExecuteCurrentFile();
  4193. }
  4194. __finally
  4195. {
  4196. FForceExecution = false;
  4197. }
  4198. }
  4199. //---------------------------------------------------------------------------
  4200. void __fastcall TCustomScpExplorerForm::ExecuteCurrentFileWith()
  4201. {
  4202. TEditorData ExternalEditor;
  4203. ExternalEditor.Editor = edExternal;
  4204. bool Remember = false;
  4205. if (DoEditorPreferencesDialog(&ExternalEditor, Remember, epmAdHoc,
  4206. (GetSide(osCurrent) == osRemote)))
  4207. {
  4208. if (Remember)
  4209. {
  4210. TEditorList * EditorList = new TEditorList;
  4211. try
  4212. {
  4213. *EditorList = *WinConfiguration->EditorList;
  4214. bool Found = false;
  4215. int i = 0;
  4216. while (!Found && (i < EditorList->Count))
  4217. {
  4218. const TEditorPreferences * Editor = EditorList->Editors[i];
  4219. if ((Editor->Data->Editor == edExternal) &&
  4220. (Editor->Data->ExternalEditor == ExternalEditor.ExternalEditor))
  4221. {
  4222. Found = true;
  4223. }
  4224. i++;
  4225. }
  4226. if (!Found)
  4227. {
  4228. EditorList->Add(new TEditorPreferences(ExternalEditor));
  4229. WinConfiguration->EditorList = EditorList;
  4230. }
  4231. }
  4232. __finally
  4233. {
  4234. delete EditorList;
  4235. }
  4236. }
  4237. ExecuteFile(osCurrent, efExternalEditor, &ExternalEditor, true, false);
  4238. }
  4239. }
  4240. //---------------------------------------------------------------------------
  4241. void __fastcall TCustomScpExplorerForm::TerminalRemoved(TObject * Sender)
  4242. {
  4243. FEditorManager->ProcessFiles(FileTerminalRemoved, Sender);
  4244. }
  4245. //---------------------------------------------------------------------------
  4246. void __fastcall TCustomScpExplorerForm::FileTerminalRemoved(const UnicodeString FileName,
  4247. TEditedFileData & Data, TObject * /*Token*/, void * Arg)
  4248. {
  4249. TTerminal * Terminal = static_cast<TTerminal *>(Arg);
  4250. assert(Terminal != NULL);
  4251. if (Data.Terminal == Terminal)
  4252. {
  4253. Data.Terminal = NULL;
  4254. }
  4255. }
  4256. //---------------------------------------------------------------------------
  4257. void __fastcall TCustomScpExplorerForm::LastTerminalClosed(TObject * /*Sender*/)
  4258. {
  4259. try
  4260. {
  4261. TTerminalManager::Instance()->NewSession();
  4262. }
  4263. __finally
  4264. {
  4265. if (!Terminal || !Terminal->Active)
  4266. {
  4267. Application->Terminate();
  4268. }
  4269. }
  4270. }
  4271. //---------------------------------------------------------------------------
  4272. void __fastcall TCustomScpExplorerForm::TerminalListChanged(TObject * /*Sender*/)
  4273. {
  4274. TStrings * TerminalList = TTerminalManager::Instance()->TerminalList;
  4275. int ActiveTerminalIndex = TTerminalManager::Instance()->ActiveTerminalIndex;
  4276. Configuration->Usage->SetMax(L"MaxOpenedSessions", TerminalList->Count);
  4277. bool ListChanged = (TerminalList->Count + 1 != SessionsPageControl->PageCount);
  4278. if (!ListChanged)
  4279. {
  4280. int Index = 0;
  4281. while (!ListChanged && (Index < TerminalList->Count))
  4282. {
  4283. ListChanged =
  4284. (SessionsPageControl->Pages[Index]->Tag != reinterpret_cast<int>(TerminalList->Objects[Index])) ||
  4285. (SessionsPageControl->Pages[Index]->Caption != TerminalList->Strings[Index]);
  4286. Index++;
  4287. }
  4288. }
  4289. if (ListChanged)
  4290. {
  4291. SendMessage(SessionsPageControl->Handle, WM_SETREDRAW, 0, 0);
  4292. try
  4293. {
  4294. FSessionColors->Clear();
  4295. while (SessionsPageControl->PageCount > 0)
  4296. {
  4297. delete SessionsPageControl->Pages[0];
  4298. }
  4299. for (int Index = 0; Index < TerminalList->Count; Index++)
  4300. {
  4301. TTabSheet * TabSheet = new TTabSheet(SessionsPageControl);
  4302. TabSheet->Caption = TerminalList->Strings[Index];
  4303. TTerminal * Terminal = dynamic_cast<TTerminal *>(TerminalList->Objects[Index]);
  4304. TabSheet->Tag = reinterpret_cast<int>(Terminal);
  4305. TabSheet->PageControl = SessionsPageControl;
  4306. TManagedTerminal * ManagedTerminal = dynamic_cast<TManagedTerminal *>(Terminal);
  4307. TColor Color =
  4308. (ManagedTerminal == NULL) ? (TColor)0 :
  4309. ((ManagedTerminal == FTerminal) ? FSessionColor : ManagedTerminal->Color);
  4310. TabSheet->ImageIndex = AddSessionColor(Color);
  4311. }
  4312. TTabSheet * TabSheet = new TTabSheet(SessionsPageControl);
  4313. TabSheet->Caption = L" +";
  4314. TabSheet->PageControl = SessionsPageControl;
  4315. TabSheet->ImageIndex = -1;
  4316. }
  4317. __finally
  4318. {
  4319. SendMessage(SessionsPageControl->Handle, WM_SETREDRAW, 1, 0);
  4320. }
  4321. }
  4322. SessionsPageControl->ActivePageIndex = ActiveTerminalIndex;
  4323. }
  4324. //---------------------------------------------------------------------------
  4325. void __fastcall TCustomScpExplorerForm::SessionsPageControlChange(TObject * /*Sender*/)
  4326. {
  4327. assert(SessionsPageControl->ActivePage != NULL);
  4328. TTerminal * Terminal = reinterpret_cast<TTerminal *>(SessionsPageControl->ActivePage->Tag);
  4329. if (Terminal != NULL)
  4330. {
  4331. TTerminalManager::Instance()->ActiveTerminal = Terminal;
  4332. }
  4333. else
  4334. {
  4335. try
  4336. {
  4337. NewSession();
  4338. }
  4339. __finally
  4340. {
  4341. TerminalListChanged(NULL);
  4342. }
  4343. FSessionsPageControlNewSessionTime = Now();
  4344. }
  4345. }
  4346. //---------------------------------------------------------------------------
  4347. void __fastcall TCustomScpExplorerForm::TransferListChange(TObject * Sender)
  4348. {
  4349. TTBXStringList * TransferList = dynamic_cast<TTBXStringList *>(Sender);
  4350. assert(TransferList != NULL);
  4351. UnicodeString Name;
  4352. if (TransferList->ItemIndex <= 0)
  4353. {
  4354. Name = L"";
  4355. }
  4356. else
  4357. {
  4358. Name = GUIConfiguration->CopyParamList->Names[TransferList->ItemIndex - 1];
  4359. }
  4360. if (FCopyParamAutoSelected.IsEmpty())
  4361. {
  4362. // if previous preset was not autoselected, make new preset the "default"
  4363. FCopyParamDefault = Name;
  4364. }
  4365. GUIConfiguration->CopyParamCurrent = Name;
  4366. }
  4367. //---------------------------------------------------------------------------
  4368. void __fastcall TCustomScpExplorerForm::UpdateTransferLabel()
  4369. {
  4370. // sanity check
  4371. bool ExistingPreset =
  4372. (FTransferListHoverIndex >= 0) &&
  4373. (FTransferListHoverIndex < 1 + GUIConfiguration->CopyParamList->Count);
  4374. assert(ExistingPreset);
  4375. if (ExistingPreset)
  4376. {
  4377. HDC DC = GetDC(0);
  4378. TCanvas * Canvas = new TCanvas();
  4379. try
  4380. {
  4381. Canvas->Handle = DC;
  4382. Canvas->Font = ToolbarFont;
  4383. UnicodeString Name;
  4384. if (FTransferListHoverIndex == 0)
  4385. {
  4386. Name = L"";
  4387. }
  4388. else
  4389. {
  4390. Name = GUIConfiguration->CopyParamList->Names[FTransferListHoverIndex - 1];
  4391. }
  4392. TTBXLabelItem * TransferLabel = dynamic_cast<TTBXLabelItem*>(
  4393. static_cast<TComponent*>(GetComponent(fcTransferLabel)));
  4394. TTBXStringList * TransferList = dynamic_cast<TTBXStringList*>(
  4395. static_cast<TObject*>(GetComponent(fcTransferList)));
  4396. UnicodeString InfoStr =
  4397. GUIConfiguration->CopyParamPreset[Name].
  4398. GetInfoStr(L"; ",
  4399. FLAGMASK(Terminal != NULL, Terminal->UsableCopyParamAttrs(0).General));
  4400. int MaxWidth = TransferList->MinWidth - (2 * TransferLabel->Margin) - 10;
  4401. if (Canvas->TextExtent(InfoStr).cx > MaxWidth)
  4402. {
  4403. UnicodeString Ellipsis = L"...";
  4404. while (Canvas->TextExtent(InfoStr + Ellipsis).cx > MaxWidth)
  4405. {
  4406. InfoStr.SetLength(InfoStr.Length() - 1);
  4407. }
  4408. InfoStr += Ellipsis;
  4409. }
  4410. // UpdateCaption does not cause invalidation of whole submenu, while
  4411. // setting Caption property does.
  4412. // also it probably does not resize the label, even if necessary
  4413. // (we do not want that anyway)
  4414. TransferLabel->UpdateCaption(InfoStr);
  4415. }
  4416. __finally
  4417. {
  4418. Canvas->Handle = NULL;
  4419. ReleaseDC(0, DC);
  4420. delete Canvas;
  4421. }
  4422. }
  4423. }
  4424. //---------------------------------------------------------------------------
  4425. void __fastcall TCustomScpExplorerForm::TransferListDrawItem(
  4426. TTBXCustomList * /*Sender*/, TCanvas * /*ACanvas*/, const TRect & /*ARect*/,
  4427. int /*AIndex*/, int AHoverIndex, bool & /*DrawDefault*/)
  4428. {
  4429. if (FTransferListHoverIndex != AHoverIndex)
  4430. {
  4431. FTransferListHoverIndex = AHoverIndex;
  4432. UpdateTransferLabel();
  4433. }
  4434. }
  4435. //---------------------------------------------------------------------------
  4436. void __fastcall TCustomScpExplorerForm::WMAppCommand(TMessage & Message)
  4437. {
  4438. int Command = GET_APPCOMMAND_LPARAM(Message.LParam);
  4439. TShiftState Shift = KeyDataToShiftState(GET_KEYSTATE_LPARAM(Message.LParam));
  4440. if ((Shift * (TShiftState() << ssShift << ssAlt << ssCtrl)).Empty())
  4441. {
  4442. if (Command == _APPCOMMAND_BROWSER_FAVORITES)
  4443. {
  4444. OpenDirectory(GetSide(osCurrent));
  4445. Message.Result = 1;
  4446. }
  4447. else
  4448. {
  4449. TForm::Dispatch(&Message);
  4450. }
  4451. }
  4452. else
  4453. {
  4454. TForm::Dispatch(&Message);
  4455. }
  4456. }
  4457. //---------------------------------------------------------------------------
  4458. void __fastcall TCustomScpExplorerForm::CMAppSysCommand(TMessage & Message)
  4459. {
  4460. TWMSysCommand * SysCommand = (TWMSysCommand *)Message.LParam;
  4461. if (SysCommand->CmdType != SC_KEYMENU || !FIgnoreNextSysCommand)
  4462. {
  4463. FIgnoreNextSysCommand = false;
  4464. TForm::Dispatch(&Message);
  4465. }
  4466. else
  4467. {
  4468. Message.Result = 1;
  4469. }
  4470. }
  4471. //---------------------------------------------------------------------------
  4472. void __fastcall TCustomScpExplorerForm::WMSysCommand(TMessage & Message)
  4473. {
  4474. // The four low-order bits are used internally by Windows
  4475. unsigned int Cmd = (Message.WParam & 0xFFF0);
  4476. // SC_RESTORE, SC_MAXIMIZE, SC_MINIMIZE - buttons on windows title
  4477. // SC_DEFAULT - double click on windows title (does not work, at least on WinXP)
  4478. // 61730 - restore thru double click - undocumented
  4479. // 61490 - maximize thru double click - undocumented
  4480. if ((Cmd == SC_RESTORE) || (Cmd == SC_MAXIMIZE) ||
  4481. (Cmd == SC_MINIMIZE) || (Cmd == SC_DEFAULT))
  4482. {
  4483. SysResizing(Cmd);
  4484. }
  4485. TForm::Dispatch(&Message);
  4486. }
  4487. //---------------------------------------------------------------------------
  4488. void __fastcall TCustomScpExplorerForm::SysResizing(unsigned int /*Cmd*/)
  4489. {
  4490. }
  4491. //---------------------------------------------------------------------------
  4492. void __fastcall TCustomScpExplorerForm::DoShow()
  4493. {
  4494. // only now are the controls resized finally, so the size constraints
  4495. // will not conflict with possibly very small window size
  4496. RestoreFormParams();
  4497. FixControlsPlacement();
  4498. if (Position == poDefaultPosOnly)
  4499. {
  4500. CutFormToDesktop(this);
  4501. }
  4502. TForm::DoShow();
  4503. FSessionsDragDropFilesEx->DragDropControl = SessionsPageControl;
  4504. FShowing = true;
  4505. }
  4506. //---------------------------------------------------------------------------
  4507. void __fastcall TCustomScpExplorerForm::PopupTrayBalloon(TTerminal * Terminal,
  4508. const UnicodeString & Str, TQueryType Type, Exception * E, unsigned int Seconds)
  4509. {
  4510. bool Do;
  4511. UnicodeString Message;
  4512. if (E == NULL)
  4513. {
  4514. Message = Str;
  4515. Do = true;
  4516. }
  4517. else
  4518. {
  4519. Do = ExceptionMessage(E, Message);
  4520. }
  4521. if (Do && WinConfiguration->BalloonNotifications)
  4522. {
  4523. const ResourceString * Captions[] = { &_SMsgDlgConfirm, &_SMsgDlgWarning,
  4524. &_SMsgDlgError, &_SMsgDlgInformation, NULL };
  4525. UnicodeString Title = LoadResourceString(Captions[Type]);
  4526. if (Terminal != NULL)
  4527. {
  4528. Title = FORMAT(L"%s - %s",
  4529. (TTerminalManager::Instance()->TerminalTitle(Terminal), Title));
  4530. }
  4531. if (Seconds == 0)
  4532. {
  4533. Seconds = WinConfiguration->NotificationsTimeout;
  4534. }
  4535. FTrayIcon->PopupBalloon(Title, Message, Type, Seconds * MSecsPerSec);
  4536. }
  4537. }
  4538. //---------------------------------------------------------------------------
  4539. unsigned int __fastcall TCustomScpExplorerForm::MoreMessageDialog(const UnicodeString Message,
  4540. TStrings * MoreMessages, TQueryType Type, unsigned int Answers,
  4541. UnicodeString HelpKeyword, const TMessageParams * Params,
  4542. TTerminal * Terminal)
  4543. {
  4544. if (WinConfiguration->ContinueOnError &&
  4545. (Params != NULL) && (Params->Params & mpAllowContinueOnError) &&
  4546. FErrorList)
  4547. {
  4548. TStringList * MoreMessagesCopy = NULL;
  4549. if (MoreMessages)
  4550. {
  4551. MoreMessagesCopy = new TStringList();
  4552. MoreMessagesCopy->Assign(MoreMessages);
  4553. }
  4554. FErrorList->AddObject(Message, MoreMessagesCopy);
  4555. if (Answers & qaSkip) return qaSkip;
  4556. else
  4557. if (Answers & qaIgnore) return qaIgnore;
  4558. else
  4559. if (Answers & qaOK) return qaOK;
  4560. else
  4561. if (Answers & qaYes) return qaYes;
  4562. else
  4563. if (Answers & qaRetry) return qaRetry;
  4564. else
  4565. {
  4566. assert(false);
  4567. return qaYes;
  4568. }
  4569. }
  4570. else
  4571. {
  4572. if (FTrayIcon->Visible)
  4573. {
  4574. PopupTrayBalloon(Terminal, Message, Type);
  4575. }
  4576. unsigned int Result;
  4577. try
  4578. {
  4579. Result = ::MoreMessageDialog(Message, MoreMessages, Type, Answers, HelpKeyword, Params);
  4580. }
  4581. __finally
  4582. {
  4583. FTrayIcon->CancelBalloon();
  4584. }
  4585. return Result;
  4586. }
  4587. }
  4588. //---------------------------------------------------------------------------
  4589. void __fastcall TCustomScpExplorerForm::ShowExtendedException(
  4590. TTerminal * Terminal, Exception * E)
  4591. {
  4592. if (FTrayIcon->Visible)
  4593. {
  4594. PopupTrayBalloon(Terminal, L"", qtError, E);
  4595. }
  4596. try
  4597. {
  4598. ShowExtendedExceptionEx(Terminal, E);
  4599. }
  4600. __finally
  4601. {
  4602. FTrayIcon->CancelBalloon();
  4603. }
  4604. }
  4605. //---------------------------------------------------------------------------
  4606. void __fastcall TCustomScpExplorerForm::InactiveTerminalException(
  4607. TTerminal * Terminal, Exception * E)
  4608. {
  4609. Notify(Terminal, L"", qtError, false, NULL, E);
  4610. }
  4611. //---------------------------------------------------------------------------
  4612. void __fastcall TCustomScpExplorerForm::Notify(TTerminal * Terminal,
  4613. UnicodeString Message, TQueryType Type,
  4614. bool Important, TNotifyEvent OnClick, Exception * E)
  4615. {
  4616. if ((E == NULL) ||
  4617. ExceptionMessage(E, Message))
  4618. {
  4619. unsigned int Seconds = WinConfiguration->NotificationsTimeout;
  4620. if (Important)
  4621. {
  4622. Seconds *= 5;
  4623. }
  4624. UnicodeString NoteMessage(Message);
  4625. if (Terminal != NULL)
  4626. {
  4627. NoteMessage = FORMAT(L"%s: %s",
  4628. (TTerminalManager::Instance()->TerminalTitle(Terminal), NoteMessage));
  4629. }
  4630. if (WinConfiguration->BalloonNotifications &&
  4631. ::TTrayIcon::SupportsBalloons())
  4632. {
  4633. AddNote(NoteMessage);
  4634. PopupTrayBalloon(Terminal, Message, Type, NULL, Seconds);
  4635. }
  4636. else
  4637. {
  4638. FlashOnBackground();
  4639. PostNote(NoteMessage, Seconds, OnClick, NULL);
  4640. }
  4641. }
  4642. }
  4643. //---------------------------------------------------------------------------
  4644. void __fastcall TCustomScpExplorerForm::QueueEvent(TTerminal * ATerminal,
  4645. TTerminalQueue * /*Queue*/, TQueueEvent Event)
  4646. {
  4647. UnicodeString Message;
  4648. switch (Event)
  4649. {
  4650. case qeEmpty:
  4651. if ((ATerminal != Terminal) || !ComponentVisible[fcQueueView])
  4652. {
  4653. Message = LoadStr(BALLOON_QUEUE_EMPTY);
  4654. }
  4655. break;
  4656. case qePendingUserAction:
  4657. if ((ATerminal != Terminal) ||
  4658. (!ComponentVisible[fcQueueView] && !GUIConfiguration->QueueAutoPopup))
  4659. {
  4660. Message = LoadStr(BALLOON_QUEUE_USER_ACTION);
  4661. }
  4662. break;
  4663. default:
  4664. assert(false);
  4665. }
  4666. if (!Message.IsEmpty())
  4667. {
  4668. Notify(ATerminal, Message, qtInformation);
  4669. }
  4670. }
  4671. //---------------------------------------------------------------------------
  4672. void __fastcall TCustomScpExplorerForm::RemoteFileControlDDCreateDragFileList(
  4673. TObject * /*Sender*/, TFileList * FileList, bool & Created)
  4674. {
  4675. if (FDDExtMapFile != NULL)
  4676. {
  4677. CloseHandle(FDDExtMapFile);
  4678. FDDExtMapFile = NULL;
  4679. }
  4680. if (WinConfiguration->DDExtEnabled)
  4681. {
  4682. if (!WinConfiguration->DDExtInstalled)
  4683. {
  4684. throw Exception(LoadStr(DRAGEXT_TARGET_NOT_INSTALLED));
  4685. }
  4686. DDExtInitDrag(FileList, Created);
  4687. }
  4688. }
  4689. //---------------------------------------------------------------------------
  4690. void __fastcall TCustomScpExplorerForm::DDExtInitDrag(TFileList * FileList,
  4691. bool & Created)
  4692. {
  4693. FDragExtFakeDirectory =
  4694. ExcludeTrailingBackslash(WinConfiguration->TemporaryDir());
  4695. if (!ForceDirectories(FDragExtFakeDirectory))
  4696. {
  4697. throw Exception(FMTLOAD(CREATE_TEMP_DIR_ERROR, (FDragExtFakeDirectory)));
  4698. }
  4699. FileList->AddItem(NULL, FDragExtFakeDirectory);
  4700. Created = true;
  4701. FDDExtMapFile = CreateFileMappingA((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE,
  4702. 0, sizeof(TDragExtCommStruct), AnsiString(DRAG_EXT_MAPPING).c_str());
  4703. {
  4704. TMutexGuard Guard(FDDExtMutex, DRAGEXT_MUTEX_RELEASE_TIMEOUT);
  4705. TDragExtCommStruct* CommStruct;
  4706. CommStruct = static_cast<TDragExtCommStruct*>(MapViewOfFile(FDDExtMapFile,
  4707. FILE_MAP_ALL_ACCESS, 0, 0, 0));
  4708. assert(CommStruct != NULL);
  4709. CommStruct->Version = TDragExtCommStruct::CurrentVersion;
  4710. CommStruct->Dragging = true;
  4711. wcsncpy(CommStruct->DropDest, FDragExtFakeDirectory.c_str(),
  4712. LENOF(CommStruct->DropDest));
  4713. CommStruct->DropDest[LENOF(CommStruct->DropDest) - 1] = L'\0';
  4714. UnmapViewOfFile(CommStruct);
  4715. }
  4716. FDDMoveSlipped = false;
  4717. }
  4718. //---------------------------------------------------------------------------
  4719. bool __fastcall TCustomScpExplorerForm::RemoteFileControlFileOperation(
  4720. TObject * Sender, TFileOperation Operation, bool NoConfirmation, void * Param)
  4721. {
  4722. bool Result;
  4723. if (Sender == RemoteDirView)
  4724. {
  4725. Result = ExecuteFileOperation(Operation, osRemote, true, NoConfirmation, Param);
  4726. }
  4727. else
  4728. {
  4729. assert(Sender == RemoteDriveView);
  4730. TStrings * FileList = RemoteDriveView->DragFileList();
  4731. try
  4732. {
  4733. Result = ExecuteFileOperation(Operation, osRemote, FileList, NoConfirmation, Param);
  4734. }
  4735. __finally
  4736. {
  4737. delete FileList;
  4738. }
  4739. }
  4740. if (FDDTargetControl == RemoteDriveView)
  4741. {
  4742. RemoteDriveView->UpdateDropTarget();
  4743. }
  4744. // foRemoteMove happens when file/dir is dragged within the remote tree view
  4745. // or from tree view to dir view.
  4746. // foMove happens when file/dir is dragged from remote tree view outside of
  4747. // application via dragex
  4748. if (((Operation == foRemoteMove) || (Operation == foMove)) &&
  4749. (DropSourceControl == RemoteDriveView))
  4750. {
  4751. RemoteDriveView->UpdateDropSource();
  4752. }
  4753. return Result;
  4754. }
  4755. //---------------------------------------------------------------------------
  4756. void __fastcall TCustomScpExplorerForm::RemoteFileControlDDEnd(TObject * Sender)
  4757. {
  4758. APPLICATION_EXCEPTION_HACK_BEGIN
  4759. {
  4760. SAFE_DESTROY(FDDFileList);
  4761. if (FDDExtMapFile != NULL)
  4762. {
  4763. try
  4764. {
  4765. TDragResult DDResult = (Sender == RemoteDirView) ?
  4766. RemoteDirView->LastDDResult : RemoteDriveView->LastDDResult;
  4767. // note that we seem to never get drMove here, see also comment below
  4768. if ((DDResult == drCopy) || (DDResult == drMove) || (DDResult == drInvalid))
  4769. {
  4770. UnicodeString TargetDirectory;
  4771. TFileOperation Operation;
  4772. // drInvalid may mean drMove, see comment below
  4773. Operation = (DDResult == drCopy) ? foCopy : foMove;
  4774. if (FDDMoveSlipped)
  4775. {
  4776. Operation = foMove;
  4777. }
  4778. TTransferOperationParam Param;
  4779. bool Internal;
  4780. if (!DDGetTarget(Param.TargetDirectory, Internal))
  4781. {
  4782. // we get drInvalid both if move-d&d was intercepted by ddext,
  4783. // and when users drops on no-drop location.
  4784. // we tell the difference by existence of response from ddext,
  4785. // so we ignore absence of response in this case
  4786. if (DDResult != drInvalid)
  4787. {
  4788. throw Exception(LoadStr(DRAGEXT_TARGET_UNKNOWN));
  4789. }
  4790. }
  4791. else
  4792. {
  4793. // download using ddext
  4794. Param.Temp = false;
  4795. Param.DragDrop = true;
  4796. if (RemoteFileControlFileOperation(Sender, Operation,
  4797. !WinConfiguration->DDTransferConfirmation, &Param))
  4798. {
  4799. Configuration->Usage->Inc(
  4800. Internal ? L"DownloadsDragDropInternal" : L"DownloadsDragDropExternalExt");
  4801. }
  4802. }
  4803. }
  4804. }
  4805. __finally
  4806. {
  4807. CloseHandle(FDDExtMapFile);
  4808. FDDExtMapFile = NULL;
  4809. RemoveDir(FDragExtFakeDirectory);
  4810. FDragExtFakeDirectory = L"";
  4811. }
  4812. }
  4813. if (!FDragDropSshTerminate.IsEmpty())
  4814. {
  4815. throw ESshTerminate(NULL, FDragDropSshTerminate, FDragDropOnceDoneOperation);
  4816. }
  4817. }
  4818. APPLICATION_EXCEPTION_HACK_END;
  4819. }
  4820. //---------------------------------------------------------------------------
  4821. void __fastcall TCustomScpExplorerForm::RemoteFileControlDDGiveFeedback(
  4822. TObject * Sender, int dwEffect, HRESULT & /*Result*/)
  4823. {
  4824. HCURSOR SlippedCopyCursor;
  4825. FDDMoveSlipped =
  4826. (FDragMoveCursor != NULL) &&
  4827. (!WinConfiguration->DDAllowMoveInit) && (dwEffect == DROPEFFECT_Copy) &&
  4828. ((IsFileControl(FDDTargetControl, osRemote) && (GetKeyState(VK_CONTROL) >= 0) &&
  4829. FTerminal->IsCapable[fcRemoteMove]) ||
  4830. (IsFileControl(FDDTargetControl, osLocal) && (GetKeyState(VK_SHIFT) < 0)));
  4831. SlippedCopyCursor = FDDMoveSlipped ? FDragMoveCursor : Dragdrop::DefaultCursor;
  4832. DragDropFiles(Sender)->CHCopy = SlippedCopyCursor;
  4833. DragDropFiles(Sender)->CHScrollCopy = SlippedCopyCursor;
  4834. // Remember drop effect so we know (when user dropes files), if we copy or move
  4835. FLastDropEffect = dwEffect;
  4836. }
  4837. //---------------------------------------------------------------------------
  4838. bool __fastcall TCustomScpExplorerForm::DDGetTarget(UnicodeString & Directory, bool & Internal)
  4839. {
  4840. bool Result = false;
  4841. Enabled = false;
  4842. try
  4843. {
  4844. int Timer = 0;
  4845. while (!Result && (Timer < WinConfiguration->DDExtTimeout))
  4846. {
  4847. {
  4848. TMutexGuard Guard(FDDExtMutex, DRAGEXT_MUTEX_RELEASE_TIMEOUT);
  4849. TDragExtCommStruct* CommStruct;
  4850. CommStruct = static_cast<TDragExtCommStruct*>(MapViewOfFile(FDDExtMapFile,
  4851. FILE_MAP_ALL_ACCESS, 0, 0, 0));
  4852. assert(CommStruct != NULL);
  4853. Result = !CommStruct->Dragging;
  4854. if (Result)
  4855. {
  4856. Directory = ExtractFilePath(CommStruct->DropDest);
  4857. Internal = false;
  4858. }
  4859. UnmapViewOfFile(CommStruct);
  4860. }
  4861. if (!Result)
  4862. {
  4863. Sleep(50);
  4864. Timer += 50;
  4865. Application->ProcessMessages();
  4866. }
  4867. }
  4868. }
  4869. __finally
  4870. {
  4871. Enabled = true;
  4872. }
  4873. return Result;
  4874. }
  4875. //---------------------------------------------------------------------------
  4876. void __fastcall TCustomScpExplorerForm::AddDelayedDirectoryDeletion(
  4877. const UnicodeString TempDir, int SecDelay)
  4878. {
  4879. TDateTime Alarm = Now() + (double)((double)SecDelay*OneMillisecond);
  4880. FDelayedDeletionList->AddObject(TempDir, reinterpret_cast<TObject*>(Alarm.FileDate()));
  4881. if (FDelayedDeletionTimer == NULL)
  4882. {
  4883. assert(HandleAllocated());
  4884. FDelayedDeletionTimer = new TTimer(this);
  4885. FDelayedDeletionTimer->Interval = 10000;
  4886. FDelayedDeletionTimer->OnTimer = DoDelayedDeletion;
  4887. }
  4888. else
  4889. {
  4890. FDelayedDeletionTimer->Enabled = true;
  4891. }
  4892. }
  4893. //---------------------------------------------------------------------------
  4894. void __fastcall TCustomScpExplorerForm::DoDelayedDeletion(TObject * Sender)
  4895. {
  4896. assert(FDelayedDeletionList != NULL);
  4897. TDateTime N = Now();
  4898. TDateTime Alert;
  4899. UnicodeString Directory;
  4900. for (int Index = FDelayedDeletionList->Count-1; Index >= 0; Index--)
  4901. {
  4902. Alert = FileDateToDateTime(reinterpret_cast<int>(FDelayedDeletionList->Objects[Index]));
  4903. if ((N >= Alert) || (Sender == NULL))
  4904. {
  4905. Directory = FDelayedDeletionList->Strings[Index];
  4906. if (DeleteDirectory(ExcludeTrailingBackslash(Directory)))
  4907. {
  4908. FDelayedDeletionList->Delete(Index);
  4909. }
  4910. }
  4911. }
  4912. if (FDelayedDeletionList->Count == 0)
  4913. {
  4914. FDelayedDeletionTimer->Enabled = false;
  4915. }
  4916. }
  4917. //---------------------------------------------------------------------------
  4918. void __fastcall TCustomScpExplorerForm::RemoteFileControlDDTargetDrop()
  4919. {
  4920. if (IsFileControl(FDDTargetControl, osRemote) ||
  4921. (FDDTargetControl == SessionsPageControl))
  4922. {
  4923. TTerminal * TargetTerminal = NULL;
  4924. TFileOperation Operation = foNone;
  4925. if (FDDTargetControl == SessionsPageControl)
  4926. {
  4927. TPoint Point = SessionsPageControl->ScreenToClient(Mouse->CursorPos);
  4928. int Index = SessionsPageControl->IndexOfTabAt(Point.X, Point.Y);
  4929. // do not allow dropping on the "+" tab
  4930. TargetTerminal = reinterpret_cast<TTerminal *>(SessionsPageControl->Pages[Index]->Tag);
  4931. if (TargetTerminal != NULL)
  4932. {
  4933. if ((FLastDropEffect == DROPEFFECT_MOVE) &&
  4934. (TargetTerminal == TTerminalManager::Instance()->ActiveTerminal))
  4935. {
  4936. Operation = foRemoteMove;
  4937. }
  4938. else
  4939. {
  4940. Operation = foRemoteCopy;
  4941. }
  4942. }
  4943. }
  4944. else
  4945. {
  4946. // when move from remote side is disabled, we allow copying inside the remote
  4947. // panel, but we interpret is as moving (we also slip in the move cursor)
  4948. if ((FLastDropEffect == DROPEFFECT_MOVE) ||
  4949. (!WinConfiguration->DDAllowMoveInit && (FLastDropEffect == DROPEFFECT_COPY) &&
  4950. FDDMoveSlipped))
  4951. {
  4952. Operation = foRemoteMove;
  4953. }
  4954. else if (FLastDropEffect == DROPEFFECT_COPY)
  4955. {
  4956. Operation = foRemoteCopy;
  4957. }
  4958. }
  4959. if (Operation != foNone)
  4960. {
  4961. RemoteFileControlFileOperation(DropSourceControl,
  4962. Operation, !WinConfiguration->DDTransferConfirmation, TargetTerminal);
  4963. }
  4964. // abort drag&drop
  4965. Abort();
  4966. }
  4967. else if ((FDDExtMapFile == NULL) && (FLastDropEffect != DROPEFFECT_NONE))
  4968. {
  4969. assert(!FDragTempDir.IsEmpty());
  4970. TTransferType Type;
  4971. UnicodeString TempDir = FDragTempDir;
  4972. // We clear FDragTempDir before calling
  4973. // just in case it fail (raises exception)
  4974. FDragTempDir = L"";
  4975. Type = (FLastDropEffect & DROPEFFECT_MOVE ? ttMove : Type = ttCopy);
  4976. TGUICopyParamType CopyParams = GUIConfiguration->CurrentCopyParam;
  4977. // empty directory parameter means temp directory -> don't display it!
  4978. UnicodeString TargetDir = L"";
  4979. if (!CopyParamDialog(tdToLocal, Type, true, FDDFileList,
  4980. TargetDir, CopyParams, WinConfiguration->DDTransferConfirmation, true))
  4981. {
  4982. Abort();
  4983. }
  4984. // TargetDir is set when dropped on local file control
  4985. // (this was workaround for legacy dirview event handling, now it should be
  4986. // made prettier)
  4987. if (TargetDir.IsEmpty())
  4988. {
  4989. TargetDir = TempDir;
  4990. if (ForceDirectories(TargetDir))
  4991. {
  4992. assert(Terminal && !TargetDir.IsEmpty());
  4993. // do not attempt to warn unless we know total transfer size
  4994. FPendingTempSpaceWarn = CopyParams.CalculateSize;
  4995. try
  4996. {
  4997. FDragDropOperation = true;
  4998. // cpNewerOnly has no efect here,
  4999. // as we download to empty temp directory
  5000. int Params = cpTemporary |
  5001. (Type == ttMove ? cpDelete : 0);
  5002. DDDownload(FDDFileList, TargetDir, &CopyParams, Params);
  5003. Configuration->Usage->Inc(L"DownloadsDragDropExternalTemp");
  5004. }
  5005. __finally
  5006. {
  5007. FDragDropOperation = false;
  5008. FPendingTempSpaceWarn = false;
  5009. AddDelayedDirectoryDeletion(TargetDir, WinConfiguration->DDDeleteDelay);
  5010. }
  5011. }
  5012. else
  5013. {
  5014. throw Exception(FMTLOAD(CREATE_TEMP_DIR_ERROR, (TargetDir)));
  5015. }
  5016. }
  5017. }
  5018. }
  5019. //---------------------------------------------------------------------------
  5020. void __fastcall TCustomScpExplorerForm::DDDownload(TStrings * FilesToCopy,
  5021. const UnicodeString TargetDir, const TCopyParamType * CopyParam, int Params)
  5022. {
  5023. UpdateCopyParamCounters(*CopyParam);
  5024. Terminal->CopyToLocal(FilesToCopy, TargetDir, CopyParam, Params);
  5025. if (FLAGSET(Params, cpDelete) && (DropSourceControl == RemoteDriveView))
  5026. {
  5027. RemoteDriveView->UpdateDropSource();
  5028. }
  5029. }
  5030. //---------------------------------------------------------------------------
  5031. class TFakeDataObjectFilesEx : public TDataObjectFilesEx
  5032. {
  5033. public:
  5034. __fastcall TFakeDataObjectFilesEx(TFileList * AFileList, bool RenderPIDL,
  5035. bool RenderFilename) : TDataObjectFilesEx(AFileList, RenderPIDL, RenderFilename)
  5036. {
  5037. }
  5038. virtual bool __fastcall AllowData(const tagFORMATETC & FormatEtc)
  5039. {
  5040. return (FormatEtc.cfFormat == CF_HDROP) ? false :
  5041. TDataObjectFilesEx::AllowData(FormatEtc);
  5042. }
  5043. };
  5044. //---------------------------------------------------------------------------
  5045. void __fastcall TCustomScpExplorerForm::RemoteFileControlDDCreateDataObject(
  5046. TObject * Sender, TDataObject *& DataObject)
  5047. {
  5048. if (FDDExtMapFile != NULL)
  5049. {
  5050. TFileList * FileList = DragDropFiles(Sender)->FileList;
  5051. if (!FileList->RenderPIDLs() || !FileList->RenderNames())
  5052. {
  5053. Abort();
  5054. }
  5055. if (FileList->Count > 0)
  5056. {
  5057. TDataObjectFilesEx * FilesObject = new TFakeDataObjectFilesEx(FileList, true, true);
  5058. if (!FilesObject->IsValid(true, true))
  5059. {
  5060. FilesObject->_Release();
  5061. }
  5062. else
  5063. {
  5064. DataObject = FilesObject;
  5065. }
  5066. }
  5067. }
  5068. }
  5069. //---------------------------------------------------------------------------
  5070. void __fastcall TCustomScpExplorerForm::GoToCommandLine()
  5071. {
  5072. assert(false);
  5073. }
  5074. //---------------------------------------------------------------------------
  5075. void __fastcall TCustomScpExplorerForm::GoToTree()
  5076. {
  5077. ComponentVisible[fcRemoteTree] = true;
  5078. RemoteDriveView->SetFocus();
  5079. }
  5080. //---------------------------------------------------------------------------
  5081. void __fastcall TCustomScpExplorerForm::PanelExport(TOperationSide Side,
  5082. TPanelExport Export, TPanelExportDestination Destination, bool OnFocused)
  5083. {
  5084. Side = GetSide(Side);
  5085. TCustomDirView * DirView = this->DirView(Side);
  5086. TStringList * ExportData = new TStringList();
  5087. try
  5088. {
  5089. switch (Export)
  5090. {
  5091. case pePath:
  5092. ExportData->Add(DirView->PathName);
  5093. break;
  5094. case peFileList:
  5095. case peFullFileList:
  5096. {
  5097. bool FullPath = (Export == peFullFileList);
  5098. DirView->CreateFileList(OnFocused, FullPath, ExportData);
  5099. UnicodeString FileName;
  5100. for (int Index = 0; Index < ExportData->Count; Index++)
  5101. {
  5102. if (ExportData->Strings[Index].Pos(L" ") > 0)
  5103. {
  5104. ExportData->Strings[Index] = FORMAT(L"\"%s\"", (ExportData->Strings[Index]));
  5105. }
  5106. }
  5107. }
  5108. break;
  5109. case peUrl:
  5110. {
  5111. assert(DirView == RemoteDirView);
  5112. DirView->CreateFileList(OnFocused, true, ExportData);
  5113. for (int Index = 0; Index < ExportData->Count; Index++)
  5114. {
  5115. ExportData->Strings[Index] =
  5116. FTerminal->FileUrl(ExportData->Strings[Index]);
  5117. }
  5118. }
  5119. break;
  5120. default:
  5121. assert(false);
  5122. }
  5123. PanelExportStore(Side, Export, Destination, ExportData);
  5124. }
  5125. __finally
  5126. {
  5127. delete ExportData;
  5128. }
  5129. }
  5130. //---------------------------------------------------------------------------
  5131. void __fastcall TCustomScpExplorerForm::PanelExportStore(TOperationSide /*Side*/,
  5132. TPanelExport /*Export*/, TPanelExportDestination Destination,
  5133. TStringList * ExportData)
  5134. {
  5135. if (Destination == pedClipboard)
  5136. {
  5137. CopyToClipboard(ExportData);
  5138. }
  5139. else
  5140. {
  5141. assert(false);
  5142. }
  5143. }
  5144. //---------------------------------------------------------------------------
  5145. void __fastcall TCustomScpExplorerForm::Filter(TOperationSide Side)
  5146. {
  5147. TCustomDirView * DirView = this->DirView(Side);
  5148. TFileFilter Filter;
  5149. DefaultFileFilter(Filter);
  5150. Filter.Masks = DirView->Mask;
  5151. if (DoFilterMaskDialog(DirView, &Filter))
  5152. {
  5153. DirView->Mask = TFileMasks::NormalizeMask(Filter.Masks);
  5154. }
  5155. }
  5156. //---------------------------------------------------------------------------
  5157. TQueueOperation __fastcall TCustomScpExplorerForm::DefaultQueueOperation()
  5158. {
  5159. return FQueueController->DefaultOperation();
  5160. }
  5161. //---------------------------------------------------------------------------
  5162. bool __fastcall TCustomScpExplorerForm::AllowQueueOperation(
  5163. TQueueOperation Operation, void ** Param)
  5164. {
  5165. switch (Operation)
  5166. {
  5167. case qoPreferences:
  5168. return true;
  5169. case qoGoTo:
  5170. return ComponentVisible[fcQueueView];
  5171. case qoOnceEmpty:
  5172. return !FQueueController->Empty;
  5173. default:
  5174. return FQueueController->AllowOperation(Operation, Param);
  5175. }
  5176. }
  5177. //---------------------------------------------------------------------------
  5178. void __fastcall TCustomScpExplorerForm::ExecuteQueueOperation(
  5179. TQueueOperation Operation, void * Param)
  5180. {
  5181. if (Operation == qoGoTo)
  5182. {
  5183. assert(QueueView2->Visible);
  5184. QueueView2->SetFocus();
  5185. }
  5186. else if (Operation == qoPreferences)
  5187. {
  5188. PreferencesDialog(pmQueue);
  5189. }
  5190. else
  5191. {
  5192. FQueueController->ExecuteOperation(Operation, Param);
  5193. }
  5194. }
  5195. //---------------------------------------------------------------------------
  5196. bool __fastcall TCustomScpExplorerForm::GetQueueEnabled()
  5197. {
  5198. return (Queue != NULL) && Queue->Enabled;
  5199. }
  5200. //---------------------------------------------------------------------------
  5201. void __fastcall TCustomScpExplorerForm::ToggleQueueEnabled()
  5202. {
  5203. assert(Queue != NULL);
  5204. if (Queue != NULL)
  5205. {
  5206. Queue->Enabled = !Queue->Enabled;
  5207. }
  5208. }
  5209. //---------------------------------------------------------------------------
  5210. void __fastcall TCustomScpExplorerForm::QueueView2ContextPopup(
  5211. TObject * /*Sender*/, TPoint & /*MousePos*/, bool & /*Handled*/)
  5212. {
  5213. FQueueActedItem = QueueView2->ItemFocused;
  5214. }
  5215. //---------------------------------------------------------------------------
  5216. /*virtual*/ int __fastcall TCustomScpExplorerForm::GetStaticComponentsHeight()
  5217. {
  5218. return TopDock->Height + QueueSplitter->Height;
  5219. }
  5220. //---------------------------------------------------------------------------
  5221. void __fastcall TCustomScpExplorerForm::QueueSplitterCanResize(
  5222. TObject * /*Sender*/, int & NewSize, bool & Accept)
  5223. {
  5224. // when queue is hidden by double-clicking splitter, stray attempt to
  5225. // resize the panel with strange value arrives, make sure it is ignored
  5226. if (ComponentVisible[fcQueueView])
  5227. {
  5228. int HeightLimit = ClientHeight - GetStaticComponentsHeight() -
  5229. RemotePanel->Constraints->MinHeight;
  5230. if (NewSize > HeightLimit)
  5231. {
  5232. NewSize = HeightLimit;
  5233. }
  5234. }
  5235. else
  5236. {
  5237. Accept = false;
  5238. }
  5239. }
  5240. //---------------------------------------------------------------------------
  5241. void __fastcall TCustomScpExplorerForm::QueueView2StartDrag(TObject * /*Sender*/,
  5242. TDragObject *& /*DragObject*/)
  5243. {
  5244. FQueueActedItem = QueueView2->ItemFocused;
  5245. }
  5246. //---------------------------------------------------------------------------
  5247. void __fastcall TCustomScpExplorerForm::QueueView2DragOver(TObject * /*Sender*/,
  5248. TObject * Source, int X, int Y, TDragState /*State*/, bool & Accept)
  5249. {
  5250. Accept = true;
  5251. if (Source == QueueView2)
  5252. {
  5253. TListItem * DropTarget = QueueView2->GetItemAt(X, Y);
  5254. Accept = (DropTarget != NULL) && (FQueueActedItem != NULL);
  5255. if (Accept)
  5256. {
  5257. TQueueItemProxy * QueueItem;
  5258. TQueueItemProxy * DestQueueItem;
  5259. QueueItem = static_cast<TQueueItemProxy *>(FQueueActedItem->Data);
  5260. DestQueueItem = static_cast<TQueueItemProxy *>(DropTarget->Data);
  5261. Accept = (QueueItem != DestQueueItem) &&
  5262. (QueueItem->Status == TQueueItem::qsPending) &&
  5263. (DestQueueItem->Status == TQueueItem::qsPending);
  5264. }
  5265. }
  5266. }
  5267. //---------------------------------------------------------------------------
  5268. void __fastcall TCustomScpExplorerForm::QueueView2DragDrop(TObject * /*Sender*/,
  5269. TObject * /*Source*/, int /*X*/, int /*Y*/)
  5270. {
  5271. if ((FQueueActedItem != NULL) && (QueueView2->DropTarget != NULL))
  5272. {
  5273. TQueueItemProxy * QueueItem;
  5274. TQueueItemProxy * DestQueueItem;
  5275. QueueItem = static_cast<TQueueItemProxy *>(FQueueActedItem->Data);
  5276. DestQueueItem = static_cast<TQueueItemProxy *>(QueueView2->DropTarget->Data);
  5277. QueueItem->Move(DestQueueItem);
  5278. }
  5279. }
  5280. //---------------------------------------------------------------------------
  5281. void __fastcall TCustomScpExplorerForm::QueueView2Enter(TObject * /*Sender*/)
  5282. {
  5283. if ((QueueView2->ItemFocused == NULL) &&
  5284. (QueueView2->Items->Count > 0))
  5285. {
  5286. QueueView2->ItemFocused = QueueView2->Items->Item[0];
  5287. }
  5288. }
  5289. //---------------------------------------------------------------------------
  5290. void __fastcall TCustomScpExplorerForm::QueueView2SelectItem(
  5291. TObject * /*Sender*/, TListItem * /*Item*/, bool Selected)
  5292. {
  5293. if (Selected)
  5294. {
  5295. NonVisualDataModule->UpdateNonVisibleActions();
  5296. }
  5297. }
  5298. //---------------------------------------------------------------------------
  5299. TDragDropFilesEx * __fastcall TCustomScpExplorerForm::DragDropFiles(TObject * Sender)
  5300. {
  5301. TDragDropFilesEx * Result = NULL;
  5302. if (Sender == SessionsPageControl)
  5303. {
  5304. Result = FSessionsDragDropFilesEx;
  5305. }
  5306. else
  5307. {
  5308. TCustomDirView * DirView = dynamic_cast<TCustomDirView *>(Sender);
  5309. if (DirView != NULL)
  5310. {
  5311. Result = DirView->DragDropFilesEx;
  5312. }
  5313. else
  5314. {
  5315. TCustomDriveView * DriveView = dynamic_cast<TCustomDriveView *>(Sender);
  5316. if (DriveView != NULL)
  5317. {
  5318. Result = DriveView->DragDropFilesEx;
  5319. }
  5320. }
  5321. }
  5322. assert(Result != NULL);
  5323. return Result;
  5324. }
  5325. //---------------------------------------------------------------------------
  5326. void __fastcall TCustomScpExplorerForm::RemoteFileControlDragDropFileOperation(
  5327. TObject * Sender, int Effect, UnicodeString TargetPath)
  5328. {
  5329. TFileOperation Operation;
  5330. switch (Effect)
  5331. {
  5332. case DROPEFFECT_MOVE:
  5333. Operation = foMove;
  5334. break;
  5335. case DROPEFFECT_COPY:
  5336. // occures on WinXP (reported by user)
  5337. default:
  5338. Operation = foCopy;
  5339. break;
  5340. };
  5341. TStrings * FileList = new TStringList();
  5342. try
  5343. {
  5344. TDragDropFilesEx * DragDropFilesEx = DragDropFiles(Sender);
  5345. for (int Index = 0; Index < DragDropFilesEx->FileList->Count; Index++)
  5346. {
  5347. FileList->Add(DragDropFilesEx->FileList->Items[Index]->Name);
  5348. }
  5349. FDragDropOperation = true;
  5350. TTransferOperationParam Param;
  5351. Param.TargetDirectory = TargetPath;
  5352. // upload, no temp dirs
  5353. Param.Temp = false;
  5354. Param.DragDrop = true;
  5355. if (ExecuteFileOperation(Operation, osLocal, FileList,
  5356. !WinConfiguration->DDTransferConfirmation, &Param))
  5357. {
  5358. if (IsFileControl(DropSourceControl, osLocal))
  5359. {
  5360. Configuration->Usage->Inc(L"UploadsDragDropInternal");
  5361. }
  5362. else
  5363. {
  5364. Configuration->Usage->Inc(L"UploadsDragDropExternal");
  5365. }
  5366. }
  5367. }
  5368. __finally
  5369. {
  5370. FDragDropOperation = false;
  5371. delete FileList;
  5372. }
  5373. }
  5374. //---------------------------------------------------------------------------
  5375. void __fastcall TCustomScpExplorerForm::RemoteFileControlDDFileOperation(
  5376. TObject * Sender, int Effect, UnicodeString /*SourcePath*/,
  5377. UnicodeString TargetPath, bool & /*DoOperation*/)
  5378. {
  5379. APPLICATION_EXCEPTION_HACK_BEGIN
  5380. {
  5381. RemoteFileControlDragDropFileOperation(Sender, Effect, TargetPath);
  5382. }
  5383. APPLICATION_EXCEPTION_HACK_END;
  5384. }
  5385. //---------------------------------------------------------------------------
  5386. void __fastcall TCustomScpExplorerForm::RemoteFileContolDDChooseEffect(
  5387. TObject * Sender, int grfKeyState, int & dwEffect)
  5388. {
  5389. // if any drop effect is allowed at all (e.g. no drop to self and drop to parent)
  5390. if ((dwEffect != DROPEFFECT_None) &&
  5391. IsFileControl(DropSourceControl, osRemote))
  5392. {
  5393. // do not allow drop on remote panel (on free space, still allow drop on directories)
  5394. if ((Sender == RemoteDirView) && (DropSourceControl == RemoteDirView) &&
  5395. (RemoteDirView->DropTarget == NULL))
  5396. {
  5397. dwEffect = DROPEFFECT_None;
  5398. }
  5399. else
  5400. {
  5401. if (dwEffect == DROPEFFECT_Copy)
  5402. {
  5403. bool MoveCapable = FTerminal->IsCapable[fcRemoteMove];
  5404. // currently we support copying always (at least via temporary directory);
  5405. // remove associated checks once this all proves stable andworking
  5406. bool CopyCapable = true;
  5407. // if we do not support neither of operations, there's no discussion
  5408. if (!MoveCapable && !CopyCapable)
  5409. {
  5410. dwEffect = DROPEFFECT_None;
  5411. }
  5412. // when moving is disabled, we need to keep effect to "copy",
  5413. // which will be later interpretted as move (with slipped-in cursor)
  5414. else if (!WinConfiguration->DDAllowMoveInit && FLAGCLEAR(grfKeyState, MK_CONTROL))
  5415. {
  5416. // no-op, keep copy
  5417. }
  5418. else
  5419. {
  5420. // The default effect inside remote panel is move,
  5421. // unless we do not support it, but support copy
  5422. if (FLAGCLEAR(grfKeyState, MK_CONTROL))
  5423. {
  5424. dwEffect = MoveCapable ? DROPEFFECT_Move : DROPEFFECT_Copy;
  5425. }
  5426. else
  5427. {
  5428. // with ctrl-down, we want copy unless it is not supported
  5429. dwEffect = CopyCapable ? DROPEFFECT_Copy : DROPEFFECT_None;
  5430. }
  5431. }
  5432. }
  5433. }
  5434. }
  5435. }
  5436. //---------------------------------------------------------------------------
  5437. void __fastcall TCustomScpExplorerForm::RemoteFileControlDDDragFileName(
  5438. TObject * Sender, TRemoteFile * File, UnicodeString & FileName)
  5439. {
  5440. if (FDDTotalSize >= 0)
  5441. {
  5442. if (File->IsDirectory)
  5443. {
  5444. FDDTotalSize = -1;
  5445. }
  5446. else
  5447. {
  5448. FDDTotalSize += File->Size;
  5449. }
  5450. }
  5451. assert(!FDragTempDir.IsEmpty());
  5452. // TODO: this is quite ineffective
  5453. // TODO: what if invalid character replacement is disabled?
  5454. FileName = FDragTempDir + GUIConfiguration->CurrentCopyParam.ValidLocalFileName(File->FileName);
  5455. UnicodeString TransferFileName;
  5456. if (Sender == RemoteDriveView)
  5457. {
  5458. TransferFileName = UnixExcludeTrailingBackslash(File->FullFileName);
  5459. }
  5460. else
  5461. {
  5462. TransferFileName = File->FileName;
  5463. }
  5464. FDDFileList->AddObject(TransferFileName, File);
  5465. }
  5466. //---------------------------------------------------------------------------
  5467. void __fastcall TCustomScpExplorerForm::RemoteFileControlDDDragDetect(
  5468. TObject * /*Sender*/, int /*grfKeyState*/, const TPoint & /*DetectStart*/,
  5469. const TPoint & /*Point*/, TDragDetectStatus /*DragStatus*/)
  5470. {
  5471. // sometimes we do not get DDEnd so the list is not released
  5472. SAFE_DESTROY(FDDFileList);
  5473. FDDFileList = new TStringList();
  5474. FDragTempDir = WinConfiguration->TemporaryDir();
  5475. FDDTotalSize = 0;
  5476. FDragDropSshTerminate = L"";
  5477. FDragDropOnceDoneOperation = odoIdle;
  5478. }
  5479. //---------------------------------------------------------------------------
  5480. void __fastcall TCustomScpExplorerForm::RemoteFileControlDDQueryContinueDrag(
  5481. TObject * /*Sender*/, BOOL /*FEscapePressed*/, int /*grfKeyState*/,
  5482. HRESULT & Result)
  5483. {
  5484. APPLICATION_EXCEPTION_HACK_BEGIN
  5485. {
  5486. if (Result == DRAGDROP_S_DROP)
  5487. {
  5488. try
  5489. {
  5490. GlobalDragImageList->HideDragImage();
  5491. try
  5492. {
  5493. RemoteFileControlDDTargetDrop();
  5494. }
  5495. catch(ESshTerminate & E)
  5496. {
  5497. assert(E.MoreMessages == NULL); // not supported
  5498. assert(!E.Message.IsEmpty());
  5499. FDragDropSshTerminate = E.Message;
  5500. FDragDropOnceDoneOperation = E.Operation;
  5501. }
  5502. }
  5503. catch (Exception &E)
  5504. {
  5505. // If downloading fails we need to cancel drag&drop, otherwise
  5506. // Explorer shows error
  5507. // But by the way exception probably never reach this point as
  5508. // it's catched on way
  5509. Result = DRAGDROP_S_CANCEL;
  5510. assert(Terminal != NULL);
  5511. Terminal->ShowExtendedException(&E);
  5512. }
  5513. }
  5514. }
  5515. APPLICATION_EXCEPTION_HACK_END
  5516. }
  5517. //---------------------------------------------------------------------------
  5518. void __fastcall TCustomScpExplorerForm::DirViewMatchMask(
  5519. TObject * /*Sender*/, UnicodeString FileName, bool Directory, __int64 Size,
  5520. TDateTime Modification, UnicodeString Masks, bool & Matches)
  5521. {
  5522. TFileMasks::TParams MaskParams;
  5523. MaskParams.Size = Size;
  5524. MaskParams.Modification = Modification;
  5525. // this does not re-parse the mask if it is the same as the last time
  5526. FDirViewMatchMask = Masks;
  5527. Matches = FDirViewMatchMask.Matches(FileName, Directory, UnicodeString(L""), &MaskParams);
  5528. }
  5529. //---------------------------------------------------------------------------
  5530. void __fastcall TCustomScpExplorerForm::RemoteDirViewGetOverlay(
  5531. TObject * Sender, TListItem * Item, WORD & Indexes)
  5532. {
  5533. TCustomDirView * DirView = reinterpret_cast<TCustomDirView *>(Sender);
  5534. UnicodeString Ext;
  5535. if (DirView == RemoteDirView)
  5536. {
  5537. Ext = UnixExtractFileExt(DirView->ItemFileName(Item));
  5538. }
  5539. else
  5540. {
  5541. Ext = ExtractFileExt(DirView->ItemFileName(Item));
  5542. }
  5543. if (AnsiSameText(Ext, Configuration->PartialExt))
  5544. {
  5545. Indexes |= oiPartial;
  5546. }
  5547. }
  5548. //---------------------------------------------------------------------------
  5549. bool __fastcall TCustomScpExplorerForm::CanPasteFromClipBoard()
  5550. {
  5551. return
  5552. IsFormatInClipboard(CF_TEXT) ||
  5553. DirView(osCurrent)->CanPasteFromClipBoard();
  5554. }
  5555. //---------------------------------------------------------------------------
  5556. void __fastcall TCustomScpExplorerForm::PasteFromClipBoard()
  5557. {
  5558. if (DirView(osCurrent)->CanPasteFromClipBoard())
  5559. {
  5560. DirView(osCurrent)->PasteFromClipBoard();
  5561. }
  5562. else
  5563. {
  5564. UnicodeString Path;
  5565. if (TextFromClipboard(Path) && !Path.IsEmpty())
  5566. {
  5567. DirView(osCurrent)->Path = Path;
  5568. }
  5569. }
  5570. }
  5571. //---------------------------------------------------------------------------
  5572. void __fastcall TCustomScpExplorerForm::FileListFromClipboard()
  5573. {
  5574. // TBD
  5575. }
  5576. //---------------------------------------------------------------------------
  5577. UnicodeString __fastcall TCustomScpExplorerForm::FileStatusBarText(
  5578. const TStatusFileInfo & FileInfo)
  5579. {
  5580. UnicodeString Result =
  5581. FMTLOAD(FILE_INFO_FORMAT,
  5582. (FormatBytes(FileInfo.SelectedSize),
  5583. FormatBytes(FileInfo.FilesSize),
  5584. FormatFloat(L"#,##0", FileInfo.SelectedCount),
  5585. FormatFloat(L"#,##0", FileInfo.FilesCount)));
  5586. if ((FileInfo.HiddenCount > 0) || (FileInfo.FilteredCount > 0))
  5587. {
  5588. UnicodeString Ex;
  5589. if (FileInfo.HiddenCount > 0)
  5590. {
  5591. Ex = FMTLOAD(FILE_INFO_HIDDEN, (FileInfo.HiddenCount));
  5592. }
  5593. if (FileInfo.FilteredCount > 0)
  5594. {
  5595. if (!Ex.IsEmpty())
  5596. {
  5597. Ex += L" + ";
  5598. }
  5599. Ex += FMTLOAD(FILE_INFO_FILTERED, (FileInfo.FilteredCount));
  5600. }
  5601. Result = FMTLOAD(FILE_INFO_FORMAT_EX, (Result, Ex));
  5602. }
  5603. return Result;
  5604. }
  5605. //---------------------------------------------------------------------------
  5606. void __fastcall TCustomScpExplorerForm::UpdateFileStatusBar(
  5607. TTBXStatusBar * StatusBar, const TStatusFileInfo & FileInfo, int Panel)
  5608. {
  5609. UnicodeString Text = FileStatusBarText(FileInfo);
  5610. if (StatusBar->SimplePanel)
  5611. {
  5612. assert(Panel == 0);
  5613. StatusBar->SimpleText = Text;
  5614. }
  5615. else
  5616. {
  5617. StatusBar->Panels->Items[Panel]->Caption = Text;
  5618. }
  5619. }
  5620. //---------------------------------------------------------------------------
  5621. void __fastcall TCustomScpExplorerForm::RemoteStatusBarClick(
  5622. TObject * /*Sender*/)
  5623. {
  5624. RemoteDirView->SetFocus();
  5625. }
  5626. //---------------------------------------------------------------------------
  5627. void __fastcall TCustomScpExplorerForm::ToggleQueueVisibility()
  5628. {
  5629. TQueueViewConfiguration Config = WinConfiguration->QueueView;
  5630. switch (Config.Show)
  5631. {
  5632. case qvShow:
  5633. if ((FQueueStatus != NULL) && (FQueueStatus->Count > 0))
  5634. {
  5635. Config.Show = qvHide;
  5636. }
  5637. else
  5638. {
  5639. Config.Show = Config.LastHideShow;
  5640. }
  5641. break;
  5642. case qvHideWhenEmpty:
  5643. if (ComponentVisible[fcQueueView])
  5644. {
  5645. Config.Show = qvHide;
  5646. }
  5647. else
  5648. {
  5649. Config.LastHideShow = Config.Show;
  5650. Config.Show = qvShow;
  5651. }
  5652. break;
  5653. case qvHide:
  5654. Config.LastHideShow = Config.Show;
  5655. Config.Show = qvShow;
  5656. break;
  5657. }
  5658. WinConfiguration->QueueView = Config;
  5659. }
  5660. //---------------------------------------------------------------------------
  5661. UnicodeString __fastcall TCustomScpExplorerForm::PathForCaption()
  5662. {
  5663. UnicodeString Result;
  5664. if (FTerminal != NULL)
  5665. {
  5666. switch (WinConfiguration->PathInCaption)
  5667. {
  5668. case picShort:
  5669. {
  5670. Result = UnixExtractFileName(FTerminal->CurrentDirectory);
  5671. if (Result.IsEmpty())
  5672. {
  5673. Result = FTerminal->CurrentDirectory;
  5674. }
  5675. }
  5676. break;
  5677. case picFull:
  5678. Result = FTerminal->CurrentDirectory;
  5679. break;
  5680. }
  5681. }
  5682. return Result;
  5683. }
  5684. //---------------------------------------------------------------------------
  5685. void __fastcall TCustomScpExplorerForm::UpdateControls()
  5686. {
  5687. TTerminalManager::Instance()->UpdateAppTitle();
  5688. RemoteDirView->Color = (FSessionColor != 0 ? FSessionColor : clWindow);
  5689. RemoteDriveView->Color = RemoteDirView->Color;
  5690. }
  5691. //---------------------------------------------------------------------------
  5692. void __fastcall TCustomScpExplorerForm::DoDirViewLoaded(TCustomDirView * /*Sender*/)
  5693. {
  5694. UpdateControls();
  5695. }
  5696. //---------------------------------------------------------------------------
  5697. void __fastcall TCustomScpExplorerForm::DirViewLoaded(
  5698. TObject * Sender)
  5699. {
  5700. TCustomDirView * DirView = dynamic_cast<TCustomDirView *>(Sender);
  5701. assert(DirView != NULL);
  5702. DoDirViewLoaded(DirView);
  5703. TransferPresetAutoSelect();
  5704. }
  5705. //---------------------------------------------------------------------------
  5706. void __fastcall TCustomScpExplorerForm::StartUpdates()
  5707. {
  5708. TUpdatesConfiguration Updates = WinConfiguration->Updates;
  5709. // first run after installation
  5710. if (double(Updates.LastCheck) == 0)
  5711. {
  5712. // make sure next time there will be an update (if enabled)
  5713. Updates.LastCheck = TDateTime(1);
  5714. WinConfiguration->Updates = Updates;
  5715. }
  5716. else if ((double(Updates.Period) > 0) &&
  5717. (Now() - Updates.LastCheck >= Updates.Period))
  5718. {
  5719. StartUpdateThread(UpdatesChecked);
  5720. }
  5721. }
  5722. //---------------------------------------------------------------------------
  5723. void __fastcall TCustomScpExplorerForm::UpdatesChecked()
  5724. {
  5725. UnicodeString Message;
  5726. bool New;
  5727. TQueryType Type;
  5728. GetUpdatesMessage(Message, New, Type, false);
  5729. if (!Message.IsEmpty())
  5730. {
  5731. if (!New && (Type != qtWarning))
  5732. {
  5733. PostNote(Message, 0, UpdatesNoteClicked, NULL);
  5734. }
  5735. else
  5736. {
  5737. Notify(NULL, Message, Type, true, UpdatesNoteClicked);
  5738. }
  5739. }
  5740. }
  5741. //---------------------------------------------------------------------------
  5742. void __fastcall TCustomScpExplorerForm::UpdatesNoteClicked(TObject * /*Sender*/)
  5743. {
  5744. CheckForUpdates(true);
  5745. }
  5746. //---------------------------------------------------------------------------
  5747. void __fastcall TCustomScpExplorerForm::GetTransferPresetAutoSelectData(
  5748. TCopyParamRuleData & Data)
  5749. {
  5750. assert(Terminal != NULL);
  5751. Data.HostName = Terminal->SessionData->HostNameExpanded;
  5752. Data.UserName = Terminal->SessionData->UserNameExpanded;
  5753. Data.RemoteDirectory = RemoteDirView->PathName;
  5754. }
  5755. //---------------------------------------------------------------------------
  5756. void __fastcall TCustomScpExplorerForm::TransferPresetAutoSelect()
  5757. {
  5758. if (FAllowTransferPresetAutoSelect)
  5759. {
  5760. assert(Terminal != NULL);
  5761. TCopyParamRuleData Data;
  5762. GetTransferPresetAutoSelectData(Data);
  5763. int CopyParamIndex = GUIConfiguration->CopyParamList->Find(Data);
  5764. UnicodeString CopyParamCurrent = GUIConfiguration->CopyParamCurrent;
  5765. if (CopyParamIndex < 0)
  5766. {
  5767. // there is no preset that matches autoselection
  5768. // set preset that we consider "default"
  5769. FCopyParamAutoSelected = L""; // forget last autoselected preset
  5770. GUIConfiguration->CopyParamCurrent = FCopyParamDefault;
  5771. }
  5772. else
  5773. {
  5774. // there is preset matching autoselection
  5775. UnicodeString CopyParamName = GUIConfiguration->CopyParamList->Names[CopyParamIndex];
  5776. if (CopyParamName == FCopyParamAutoSelected)
  5777. {
  5778. // autoselected the same preset as the last time
  5779. // make no change (i.e. preserve custom user preset, if any)
  5780. }
  5781. else
  5782. {
  5783. // autoselected the different preset then the last time (or there
  5784. // was default preset set)
  5785. FCopyParamAutoSelected = CopyParamName; // remember autoselection
  5786. GUIConfiguration->CopyParamCurrent = CopyParamName;
  5787. }
  5788. }
  5789. if (GUIConfiguration->CopyParamCurrent != CopyParamCurrent)
  5790. {
  5791. if (CopyParamIndex >= 0)
  5792. {
  5793. Configuration->Usage->Inc(L"CopyParamAutoSelects");
  5794. }
  5795. TTransferPresetNoteData * Data = new TTransferPresetNoteData;
  5796. try
  5797. {
  5798. int Fmt =
  5799. (CopyParamIndex < 0) ?
  5800. (GUIConfiguration->CopyParamIndex < 0 ? COPY_PARAM_DEFAULT_NORM : COPY_PARAM_DEFAULT_CUSTOM) :
  5801. COPY_PARAM_AUTOSELECTED;
  5802. Data->Message = FMTLOAD(Fmt, (StripHotkey(GUIConfiguration->CopyParamCurrent)));
  5803. Data->More = new TStringList();
  5804. int CopyParamAttrs = Terminal->UsableCopyParamAttrs(0).General;
  5805. UnicodeString Info = GUIConfiguration->CurrentCopyParam.GetInfoStr(L"\n",
  5806. CopyParamAttrs);
  5807. if (CopyParamIndex >= 0)
  5808. {
  5809. assert(GUIConfiguration->CopyParamList->Rules[CopyParamIndex] != NULL);
  5810. Info = FORMAT(L"%s\n \n%s", (Info,
  5811. FMTLOAD(COPY_PARAM_RULE,
  5812. (GUIConfiguration->CopyParamList->Rules[CopyParamIndex]->GetInfoStr(L"\n")))));
  5813. }
  5814. Data->More->Text = Info;
  5815. if (WinConfiguration->CopyParamAutoSelectNotice)
  5816. {
  5817. TransferPresetNoteMessage(Data, true);
  5818. }
  5819. else
  5820. {
  5821. PostNote(Data->Message, 0, TransferPresetNoteClicked, Data);
  5822. Data = NULL; // ownership passed
  5823. }
  5824. }
  5825. __finally
  5826. {
  5827. delete Data;
  5828. }
  5829. }
  5830. }
  5831. }
  5832. //---------------------------------------------------------------------------
  5833. void __fastcall TCustomScpExplorerForm::TransferPresetNoteMessage(
  5834. TTransferPresetNoteData * NoteData, bool AllowNeverAskAgain)
  5835. {
  5836. assert(NoteData != NULL);
  5837. TMessageParams Params(AllowNeverAskAgain ? mpNeverAskAgainCheck : 0);
  5838. TQueryButtonAlias Aliases[1];
  5839. Aliases[0].Button = qaIgnore; // "ignore" is after "ok"
  5840. Aliases[0].Alias = LoadStr(CONFIGURE_BUTTON);
  5841. Params.Aliases = Aliases;
  5842. Params.AliasesCount = LENOF(Aliases);
  5843. unsigned int Result =
  5844. MoreMessageDialog(NoteData->Message, NoteData->More, qtInformation,
  5845. qaOK | qaIgnore, HELP_COPY_PARAM_AUTOSELECTED, &Params);
  5846. switch (Result)
  5847. {
  5848. case qaNeverAskAgain:
  5849. assert(AllowNeverAskAgain);
  5850. WinConfiguration->CopyParamAutoSelectNotice = false;
  5851. break;
  5852. case qaIgnore:
  5853. PreferencesDialog(pmPresets);
  5854. break;
  5855. }
  5856. }
  5857. //---------------------------------------------------------------------------
  5858. void __fastcall TCustomScpExplorerForm::TransferPresetNoteClicked(TObject * /*Sender*/)
  5859. {
  5860. TransferPresetNoteMessage(dynamic_cast<TTransferPresetNoteData *>(FNoteData), false);
  5861. }
  5862. //---------------------------------------------------------------------------
  5863. void __fastcall TCustomScpExplorerForm::PreferencesDialog(
  5864. TPreferencesMode APreferencesMode)
  5865. {
  5866. TCopyParamRuleData Data;
  5867. GetTransferPresetAutoSelectData(Data);
  5868. TPreferencesDialogData PreferencesData;
  5869. PreferencesData.CopyParamRuleData = &Data;
  5870. DoPreferencesDialog(APreferencesMode, &PreferencesData);
  5871. }
  5872. //---------------------------------------------------------------------------
  5873. void __fastcall TCustomScpExplorerForm::AdHocCustomCommandValidate(
  5874. const TCustomCommandType & Command)
  5875. {
  5876. if (CustomCommandState(Command, FEditingFocusedAdHocCommand) <= 0)
  5877. {
  5878. throw Exception(FMTLOAD(CUSTOM_COMMAND_IMPOSSIBLE, (Command.Command)));
  5879. }
  5880. }
  5881. //---------------------------------------------------------------------------
  5882. void __fastcall TCustomScpExplorerForm::AdHocCustomCommand(bool OnFocused)
  5883. {
  5884. bool RemoteAllowed = CustomCommandRemoteAllowed();
  5885. TCustomCommandType Command;
  5886. // make sure we use local custom command when remote are not supported
  5887. if (RemoteAllowed || FLAGSET(FLastCustomCommand.Params, ccLocal))
  5888. {
  5889. Command = FLastCustomCommand;
  5890. }
  5891. else
  5892. {
  5893. Command.Params = Command.Params | ccLocal;
  5894. }
  5895. Command.Name = LoadStr(CUSTOM_COMMAND_AD_HOC_NAME);
  5896. FEditingFocusedAdHocCommand = OnFocused;
  5897. int Options = FLAGMASK(!RemoteAllowed, ccoDisableRemote);
  5898. if (DoCustomCommandDialog(Command, WinConfiguration->CustomCommandList,
  5899. ccmAdHoc, Options, AdHocCustomCommandValidate, NULL))
  5900. {
  5901. FLastCustomCommand = Command;
  5902. UpdateCustomCommandsToolbar();
  5903. ExecuteFileOperation(foCustomCommand, osRemote, OnFocused, false, &Command);
  5904. }
  5905. }
  5906. //---------------------------------------------------------------------------
  5907. void __fastcall TCustomScpExplorerForm::LastCustomCommand(bool OnFocused)
  5908. {
  5909. assert(!FLastCustomCommand.Command.IsEmpty());
  5910. int State = CustomCommandState(FLastCustomCommand, OnFocused);
  5911. assert(State > 0);
  5912. if (State <= 0)
  5913. {
  5914. throw Exception(FMTLOAD(CUSTOM_COMMAND_IMPOSSIBLE, (FLastCustomCommand.Command)));
  5915. }
  5916. ExecuteFileOperation(foCustomCommand, osRemote, OnFocused, false, &FLastCustomCommand);
  5917. }
  5918. //---------------------------------------------------------------------------
  5919. bool __fastcall TCustomScpExplorerForm::GetLastCustomCommand(bool OnFocused,
  5920. TCustomCommandType & Command, int & State)
  5921. {
  5922. bool Result = !FLastCustomCommand.Command.IsEmpty();
  5923. if (Result)
  5924. {
  5925. Command = FLastCustomCommand;
  5926. State = CustomCommandState(FLastCustomCommand, OnFocused);
  5927. }
  5928. return Result;
  5929. }
  5930. //---------------------------------------------------------------------------
  5931. void __fastcall TCustomScpExplorerForm::WhatsThis()
  5932. {
  5933. SendMessage(Handle, WM_SYSCOMMAND, SC_CONTEXTHELP, 0);
  5934. }
  5935. //---------------------------------------------------------------------------
  5936. void __fastcall TCustomScpExplorerForm::BeforeAction()
  5937. {
  5938. if (RemoteDirView->ItemFocused != NULL)
  5939. {
  5940. RemoteDirView->ItemFocused->CancelEdit();
  5941. }
  5942. }
  5943. //---------------------------------------------------------------------------
  5944. void __fastcall TCustomScpExplorerForm::PostComponentHide(Byte Component)
  5945. {
  5946. assert(ComponentVisible[Component]);
  5947. PostMessage(Handle, WM_COMPONENT_HIDE, Component, 0);
  5948. }
  5949. //---------------------------------------------------------------------------
  5950. void __fastcall TCustomScpExplorerForm::QueueSplitterDblClick(TObject * /*Sender*/)
  5951. {
  5952. // when queue panel is resized here directly, the status bar is stretched
  5953. // over whole space the panel occupied
  5954. PostComponentHide(fcQueueView);
  5955. }
  5956. //---------------------------------------------------------------------------
  5957. void __fastcall TCustomScpExplorerForm::Dispatch(void * Message)
  5958. {
  5959. TMessage * M = static_cast<TMessage*>(Message);
  5960. switch (M->Msg)
  5961. {
  5962. case CM_APPSYSCOMMAND:
  5963. CMAppSysCommand(*M);
  5964. break;
  5965. case _WM_APPCOMMAND:
  5966. WMAppCommand(*M);
  5967. break;
  5968. case WM_SYSCOMMAND:
  5969. WMSysCommand(*M);
  5970. break;
  5971. case WM_COMPONENT_HIDE:
  5972. {
  5973. Byte Component = static_cast<Byte>(M->WParam);
  5974. // sanity check
  5975. if (ComponentVisible[Component])
  5976. {
  5977. // special treatment
  5978. if (Component == fcQueueView)
  5979. {
  5980. ToggleQueueVisibility();
  5981. assert(!ComponentVisible[fcQueueView]);
  5982. }
  5983. else
  5984. {
  5985. ComponentVisible[Component] = false;
  5986. }
  5987. }
  5988. }
  5989. break;
  5990. default:
  5991. TForm::Dispatch(Message);
  5992. break;
  5993. }
  5994. }
  5995. //---------------------------------------------------------------------------
  5996. void __fastcall TCustomScpExplorerForm::FormConstrainedResize(
  5997. TObject * /*Sender*/, int & MinWidth, int & MinHeight, int & MaxWidth,
  5998. int & MaxHeight)
  5999. {
  6000. // workaround for bug in TWinControl.CalcConstraints
  6001. // Check for empty rect (restore from iconinc state) is done there only after
  6002. // call to AdjustClientRect, which enlarges the rect (for forms).
  6003. TRect R = GetClientRect();
  6004. // when restoring from iconic state, place no restrictions
  6005. if (IsRectEmpty(R))
  6006. {
  6007. MinWidth = 0;
  6008. MinHeight = 0;
  6009. MaxWidth = 32000;
  6010. MaxHeight = 32000;
  6011. }
  6012. }
  6013. //---------------------------------------------------------------------------
  6014. void __fastcall TCustomScpExplorerForm::GetSpaceAvailable(const UnicodeString Path,
  6015. TSpaceAvailable & ASpaceAvailable, bool & Close)
  6016. {
  6017. // terminal can be already closed (e.g. dropped connection)
  6018. if ((Terminal != NULL) && Terminal->IsCapable[fcCheckingSpaceAvailable])
  6019. {
  6020. Configuration->Usage->Inc(L"SpaceAvailableChecks");
  6021. try
  6022. {
  6023. Terminal->SpaceAvailable(Path, ASpaceAvailable);
  6024. }
  6025. catch(...)
  6026. {
  6027. if (!Terminal->Active)
  6028. {
  6029. Close = true;
  6030. }
  6031. throw;
  6032. }
  6033. }
  6034. }
  6035. //---------------------------------------------------------------------------
  6036. void __fastcall TCustomScpExplorerForm::FileSystemInfo()
  6037. {
  6038. const TSessionInfo & SessionInfo = Terminal->GetSessionInfo();
  6039. const TFileSystemInfo & FileSystemInfo = Terminal->GetFileSystemInfo(true);
  6040. TGetSpaceAvailable OnGetSpaceAvailable = NULL;
  6041. if (Terminal->IsCapable[fcCheckingSpaceAvailable])
  6042. {
  6043. OnGetSpaceAvailable = GetSpaceAvailable;
  6044. }
  6045. DoFileSystemInfoDialog(SessionInfo, FileSystemInfo, Terminal->CurrentDirectory,
  6046. OnGetSpaceAvailable);
  6047. }
  6048. //---------------------------------------------------------------------------
  6049. void __fastcall TCustomScpExplorerForm::SetSessionColor(TColor value)
  6050. {
  6051. if (value != FSessionColor)
  6052. {
  6053. FSessionColor = value;
  6054. TColor C = (value != 0 ? value : clNone);
  6055. TTBXColorPalette * ColorPalette = dynamic_cast<TTBXColorPalette *>(
  6056. static_cast<TObject *>(GetComponent(fcColorPalette)));
  6057. assert(ColorPalette != NULL);
  6058. ColorPalette->Color = C;
  6059. TTBXColorItem * ColorItem = dynamic_cast<TTBXColorItem *>(
  6060. static_cast<TObject *>(GetComponent(fcColorMenu)));
  6061. assert(ColorItem != NULL);
  6062. ColorItem->Color = C;
  6063. NonVisualDataModule->SessionColorPalette->Color = C;
  6064. NonVisualDataModule->ColorMenuItem->Color = C;
  6065. SessionsPageControl->ActivePage->ImageIndex = AddSessionColor(value);
  6066. UpdateControls();
  6067. }
  6068. }
  6069. //---------------------------------------------------------------------------
  6070. void __fastcall TCustomScpExplorerForm::SessionColorPick()
  6071. {
  6072. TColorDialog * Dialog = new TColorDialog(this);
  6073. try
  6074. {
  6075. Dialog->Options = Dialog->Options << cdFullOpen;
  6076. Dialog->Color = (FSessionColor != 0 ? FSessionColor : clSkyBlue);
  6077. if (Dialog->Execute())
  6078. {
  6079. SessionColor = Dialog->Color;
  6080. }
  6081. }
  6082. __finally
  6083. {
  6084. delete Dialog;
  6085. }
  6086. }
  6087. //---------------------------------------------------------------------------
  6088. bool __fastcall TCustomScpExplorerForm::CancelNote()
  6089. {
  6090. bool Result = FNoteTimer->Enabled;
  6091. if (Result)
  6092. {
  6093. // cannot cancel note too early
  6094. if (Now() - FNoteShown >
  6095. EncodeTimeVerbose(0, 0, (unsigned short)(WinConfiguration->NotificationsStickTime), 0))
  6096. {
  6097. FNoteTimer->Enabled = false;
  6098. FNote = "";
  6099. // beware that OnNoteClick may being executed
  6100. SAFE_DESTROY(FNoteData);
  6101. FOnNoteClick = NULL;
  6102. FNoteHints = FNotes->Text;
  6103. FNoteHints.Delete(FNoteHints.Length() - 1, 2);
  6104. UpdateStatusBar();
  6105. }
  6106. }
  6107. return Result;
  6108. }
  6109. //---------------------------------------------------------------------------
  6110. void __fastcall TCustomScpExplorerForm::NoteTimer(TObject * /*Sender*/)
  6111. {
  6112. assert(FNoteTimer->Enabled);
  6113. CancelNote();
  6114. }
  6115. //---------------------------------------------------------------------------
  6116. void __fastcall TCustomScpExplorerForm::AddNote(UnicodeString Note, bool UpdateNow)
  6117. {
  6118. int P = Note.Pos(L"\n");
  6119. if (P > 0)
  6120. {
  6121. Note.SetLength(P - 1);
  6122. }
  6123. FNotes->Add(FORMAT(L"[%s] %s",
  6124. (FormatDateTime(Configuration->TimeFormat, Now()), Note)));
  6125. while (FNotes->Count > 10)
  6126. {
  6127. FNotes->Delete(0);
  6128. }
  6129. if (UpdateNow)
  6130. {
  6131. FNoteHints = FNotes->Text;
  6132. FNoteHints.Delete(FNoteHints.Length() - 1, 2);
  6133. UpdateStatusBar();
  6134. }
  6135. }
  6136. //---------------------------------------------------------------------------
  6137. void __fastcall TCustomScpExplorerForm::PostNote(UnicodeString Note,
  6138. unsigned int Seconds, TNotifyEvent OnNoteClick, TObject * NoteData)
  6139. {
  6140. int P = Note.Pos(L"\n");
  6141. if (P > 0)
  6142. {
  6143. Note.SetLength(P - 1);
  6144. }
  6145. FNoteHints = FNotes->Text;
  6146. FNoteHints.Delete(FNoteHints.Length() - 1, 2);
  6147. FNote = Note;
  6148. // beware that OnNoteClick may being executed
  6149. SAFE_DESTROY(FNoteData);
  6150. FNoteData = NoteData;
  6151. FOnNoteClick = OnNoteClick;
  6152. AddNote(Note, false);
  6153. UpdateStatusBar();
  6154. FNoteShown = Now();
  6155. FNoteTimer->Enabled = false;
  6156. if (Seconds == 0)
  6157. {
  6158. Seconds = WinConfiguration->NotificationsTimeout;
  6159. }
  6160. FNoteTimer->Interval = Seconds * MSecsPerSec;
  6161. FNoteTimer->Enabled = true;
  6162. }
  6163. //---------------------------------------------------------------------------
  6164. void __fastcall TCustomScpExplorerForm::ReadDirectoryCancelled()
  6165. {
  6166. PostNote(LoadStr(DIRECTORY_READING_CANCELLED), 0, NULL, NULL);
  6167. }
  6168. //---------------------------------------------------------------------------
  6169. void __fastcall TCustomScpExplorerForm::SynchronizeBrowsingChanged()
  6170. {
  6171. if (NonVisualDataModule->SynchronizeBrowsingAction->Checked)
  6172. {
  6173. Configuration->Usage->Inc(L"SynchronizeBrowsingEnabled");
  6174. }
  6175. PostNote(FORMAT(LoadStrPart(SYNC_DIR_BROWSE_TOGGLE, 1),
  6176. (LoadStrPart(SYNC_DIR_BROWSE_TOGGLE,
  6177. (NonVisualDataModule->SynchronizeBrowsingAction->Checked ? 2 : 3)))),
  6178. 0, NULL, NULL);
  6179. }
  6180. //---------------------------------------------------------------------------
  6181. void __fastcall TCustomScpExplorerForm::ToggleShowHiddenFiles()
  6182. {
  6183. WinConfiguration->ShowHiddenFiles = !WinConfiguration->ShowHiddenFiles;
  6184. PostNote(FORMAT(LoadStrPart(SHOW_HIDDEN_FILES_TOGGLE, 1),
  6185. (LoadStrPart(SHOW_HIDDEN_FILES_TOGGLE,
  6186. (WinConfiguration->ShowHiddenFiles ? 2 : 3)))), 0, NULL, NULL);
  6187. }
  6188. //---------------------------------------------------------------------------
  6189. void __fastcall TCustomScpExplorerForm::ToggleFormatSizeBytes()
  6190. {
  6191. WinConfiguration->FormatSizeBytes = !WinConfiguration->FormatSizeBytes;
  6192. }
  6193. //---------------------------------------------------------------------------
  6194. void __fastcall TCustomScpExplorerForm::ToggleAutoReadDirectoryAfterOp()
  6195. {
  6196. Configuration->AutoReadDirectoryAfterOp = !Configuration->AutoReadDirectoryAfterOp;
  6197. PostNote(FORMAT(LoadStrPart(AUTO_READ_DIRECTORY_TOGGLE, 1),
  6198. (LoadStrPart(AUTO_READ_DIRECTORY_TOGGLE,
  6199. (Configuration->AutoReadDirectoryAfterOp ? 2 : 3)))), 0, NULL, NULL);
  6200. }
  6201. //---------------------------------------------------------------------------
  6202. void __fastcall TCustomScpExplorerForm::StatusBarPanelDblClick(
  6203. TTBXCustomStatusBar * /*Sender*/, TTBXStatusPanel * Panel)
  6204. {
  6205. if (Panel->Index == 0)
  6206. {
  6207. if (FOnNoteClick != NULL)
  6208. {
  6209. FOnNoteClick(NULL);
  6210. }
  6211. }
  6212. else
  6213. {
  6214. FileSystemInfo();
  6215. }
  6216. }
  6217. //---------------------------------------------------------------------------
  6218. void __fastcall TCustomScpExplorerForm::LockWindow()
  6219. {
  6220. // workaround:
  6221. // 1) for unknown reason, disabling window, while minimized,
  6222. // prevents it from restoring, even if it was enabled again meanwhile
  6223. // 2) when disabling the main window, while another has focus
  6224. // minimize is no longer possible ("keep up to date" dialog)
  6225. if (!IsIconic(Application->Handle) && (Screen->ActiveForm == this))
  6226. {
  6227. Enabled = false;
  6228. }
  6229. FLockLevel++;
  6230. }
  6231. //---------------------------------------------------------------------------
  6232. void __fastcall TCustomScpExplorerForm::UnlockWindow()
  6233. {
  6234. assert(FLockLevel > 0);
  6235. FLockLevel--;
  6236. if (FLockLevel == 0)
  6237. {
  6238. Enabled = true;
  6239. }
  6240. }
  6241. //---------------------------------------------------------------------------
  6242. void __fastcall TCustomScpExplorerForm::UpdateRemotePathComboBox(
  6243. TTBXComboBoxItem * RemotePathComboBox, bool TextOnly)
  6244. {
  6245. if (!TextOnly)
  6246. {
  6247. TStrings * Items = RemotePathComboBox->Strings;
  6248. Items->BeginUpdate();
  6249. try
  6250. {
  6251. Items->Clear();
  6252. UnicodeString APath = UnixExcludeTrailingBackslash(RemoteDirView->Path);
  6253. while (!IsUnixRootPath(APath))
  6254. {
  6255. int P = APath.LastDelimiter(L'/');
  6256. assert(P >= 0);
  6257. Items->Insert(0, APath.SubString(P + 1, APath.Length() - P));
  6258. APath.SetLength(P - 1);
  6259. }
  6260. Items->Insert(0, Customunixdirview_SUnixDefaultRootName);
  6261. }
  6262. __finally
  6263. {
  6264. RemotePathComboBox->ItemIndex = Items->Count - 1;
  6265. Items->EndUpdate();
  6266. }
  6267. }
  6268. }
  6269. //---------------------------------------------------------------------------
  6270. void __fastcall TCustomScpExplorerForm::RemotePathComboBoxAdjustImageIndex(
  6271. TTBXComboBoxItem * Sender, const UnicodeString /*AText*/, int AIndex,
  6272. int & ImageIndex)
  6273. {
  6274. if (AIndex < 0)
  6275. {
  6276. AIndex = Sender->ItemIndex;
  6277. }
  6278. ImageIndex = (AIndex < Sender->Strings->Count - 1 ? StdDirIcon : StdDirSelIcon);
  6279. }
  6280. //---------------------------------------------------------------------------
  6281. void __fastcall TCustomScpExplorerForm::RemotePathComboBoxDrawItem(
  6282. TTBXCustomList * /*Sender*/, TCanvas * /*ACanvas*/, TRect & ARect, int AIndex,
  6283. int /*AHoverIndex*/, bool & /*DrawDefault*/)
  6284. {
  6285. ARect.Left += (10 * AIndex);
  6286. }
  6287. //---------------------------------------------------------------------------
  6288. void __fastcall TCustomScpExplorerForm::RemotePathComboBoxMeasureWidth(
  6289. TTBXCustomList * /*Sender*/, TCanvas * /*ACanvas*/, int AIndex, int &AWidth)
  6290. {
  6291. AWidth += (10 * AIndex);
  6292. }
  6293. //---------------------------------------------------------------------------
  6294. void __fastcall TCustomScpExplorerForm::RemotePathComboBoxItemClick(
  6295. TObject * Sender)
  6296. {
  6297. TTBXComboBoxItem * RemotePathComboBox = dynamic_cast<TTBXComboBoxItem*>(Sender);
  6298. UnicodeString APath = UnixExcludeTrailingBackslash(RemoteDirView->Path);
  6299. int Index = RemotePathComboBox->ItemIndex;
  6300. while (Index < RemotePathComboBox->Strings->Count - 1)
  6301. {
  6302. APath = UnixExtractFileDir(APath);
  6303. Index++;
  6304. }
  6305. // VanDyke style paths
  6306. if (APath.IsEmpty())
  6307. {
  6308. assert(RemotePathComboBox->ItemIndex == 0);
  6309. APath = ROOTDIRECTORY;
  6310. }
  6311. if (RemoteDirView->Path != APath)
  6312. {
  6313. RemoteDirView->Path = APath;
  6314. }
  6315. }
  6316. //---------------------------------------------------------------------------
  6317. void __fastcall TCustomScpExplorerForm::RemotePathComboBoxCancel(TObject * Sender)
  6318. {
  6319. UpdateRemotePathComboBox(dynamic_cast<TTBXComboBoxItem*>(Sender), true);
  6320. }
  6321. //---------------------------------------------------------------------------
  6322. void __fastcall TCustomScpExplorerForm::ClickToolbarItem(TTBCustomItem * Item,
  6323. bool PositionCursor)
  6324. {
  6325. TTBCustomItem * TopItem = Item;
  6326. while (TopItem->Parent != NULL)
  6327. {
  6328. TopItem = TopItem->Parent;
  6329. }
  6330. TTBCustomToolbar * Toolbar = dynamic_cast<TTBCustomToolbar *>(TopItem->ParentComponent);
  6331. assert(Toolbar != NULL);
  6332. TTBItemViewer * Viewer = Toolbar->View->Find(Item);
  6333. assert(Viewer != NULL);
  6334. POINT P = Point(Viewer->BoundsRect.Left + (Viewer->BoundsRect.Width() / 2),
  6335. Viewer->BoundsRect.Top + (Viewer->BoundsRect.Height() / 2));
  6336. if (PositionCursor)
  6337. {
  6338. Mouse->CursorPos = Toolbar->ClientToScreen(P);
  6339. }
  6340. PostMessage(Toolbar->Handle, WM_LBUTTONDOWN, MK_LBUTTON,
  6341. *reinterpret_cast<LPARAM*>(&P));
  6342. }
  6343. //---------------------------------------------------------------------------
  6344. void __fastcall TCustomScpExplorerForm::DirViewEditing(
  6345. TObject * Sender, TListItem * Item, bool & /*AllowEdit*/)
  6346. {
  6347. TCustomDirView * DirView = dynamic_cast<TCustomDirView *>(Sender);
  6348. assert(DirView != NULL);
  6349. if (!WinConfiguration->RenameWholeName && !DirView->ItemIsDirectory(Item))
  6350. {
  6351. HWND Edit = ListView_GetEditControl(DirView->Handle);
  6352. // OnEditing is called also from TCustomListView::CanEdit
  6353. if (Edit != NULL)
  6354. {
  6355. EditSelectBaseName(Edit);
  6356. }
  6357. }
  6358. }
  6359. //---------------------------------------------------------------------------
  6360. void __fastcall TCustomScpExplorerForm::FormActivate(TObject * /*Sender*/)
  6361. {
  6362. Application->OnHint = ApplicationHint;
  6363. }
  6364. //---------------------------------------------------------------------------
  6365. void __fastcall TCustomScpExplorerForm::CreateWnd()
  6366. {
  6367. TForm::CreateWnd();
  6368. if (FSessionsDragDropFilesEx == NULL)
  6369. {
  6370. FSessionsDragDropFilesEx = new TDragDropFilesEx(this);
  6371. FSessionsDragDropFilesEx->AutoDetectDnD = false;
  6372. FSessionsDragDropFilesEx->NeedValid = TFileExMustDnDSet() << nvFilename;
  6373. FSessionsDragDropFilesEx->RenderDataOn = rdoEnterAndDropSync;
  6374. FSessionsDragDropFilesEx->TargetEffects = TDropEffectSet() << deCopy << deMove;
  6375. FSessionsDragDropFilesEx->OnDragOver = SessionsDDDragOver;
  6376. FSessionsDragDropFilesEx->OnProcessDropped = SessionsDDProcessDropped;
  6377. FSessionsDragDropFilesEx->OnDragEnter = SessionsDDDragEnter;
  6378. FSessionsDragDropFilesEx->OnDragLeave = SessionsDDDragLeave;
  6379. }
  6380. }
  6381. //---------------------------------------------------------------------------
  6382. void __fastcall TCustomScpExplorerForm::DestroyWnd()
  6383. {
  6384. TForm::DestroyWnd();
  6385. FSessionsDragDropFilesEx->DragDropControl = NULL;
  6386. }
  6387. //---------------------------------------------------------------------------
  6388. void __fastcall TCustomScpExplorerForm::FormShow(TObject * /*Sender*/)
  6389. {
  6390. SideEnter(FCurrentSide);
  6391. }
  6392. //---------------------------------------------------------------------------
  6393. void __fastcall TCustomScpExplorerForm::DoFindFiles(
  6394. UnicodeString Directory, const TFileMasks & FileMask,
  6395. TFileFoundEvent OnFileFound, TFindingFileEvent OnFindingFile)
  6396. {
  6397. Configuration->Usage->Inc(L"FileFinds");
  6398. FTerminal->FilesFind(Directory, FileMask, OnFileFound, OnFindingFile);
  6399. }
  6400. //---------------------------------------------------------------------------
  6401. void __fastcall TCustomScpExplorerForm::DoFocusRemotePath(UnicodeString Path)
  6402. {
  6403. RemoteDirView->Path = UnixExtractFilePath(Path);
  6404. TListItem * Item = RemoteDirView->FindFileItem(UnixExtractFileName(Path));
  6405. if (Item != NULL)
  6406. {
  6407. RemoteDirView->ItemFocused = Item;
  6408. RemoteDirView->ItemFocused->MakeVisible(false);
  6409. }
  6410. }
  6411. //---------------------------------------------------------------------------
  6412. void __fastcall TCustomScpExplorerForm::FindFiles()
  6413. {
  6414. UnicodeString Path;
  6415. if (DoFileFindDialog(RemoteDirView->Path, DoFindFiles, Path))
  6416. {
  6417. DoFocusRemotePath(Path);
  6418. }
  6419. }
  6420. //---------------------------------------------------------------------------
  6421. void __fastcall TCustomScpExplorerForm::UpdateTaskbarList(ITaskbarList3 * TaskbarList)
  6422. {
  6423. FTaskbarList = TaskbarList;
  6424. }
  6425. //---------------------------------------------------------------------------
  6426. void __fastcall TCustomScpExplorerForm::SessionsPageControlMouseDown(
  6427. TObject * /*Sender*/, TMouseButton Button, TShiftState /*Shift*/, int X, int Y)
  6428. {
  6429. int Index = SessionsPageControl->IndexOfTabAt(X, Y);
  6430. if (Index >= 0)
  6431. {
  6432. if (Button == mbRight)
  6433. {
  6434. SessionsPageControl->ActivePageIndex = Index;
  6435. SessionsPageControlChange(NULL);
  6436. }
  6437. else if (Button == mbLeft)
  6438. {
  6439. // "Mouse down" is raised only after tab is switched.
  6440. // If switching tab (switching session) takes long enough for user
  6441. // to actually release the button, "mouse down" is still raised,
  6442. // but we do not get "mouse up" event, so dragging is not cancelled,
  6443. // prevent that by not beginning dragging in the first place.
  6444. if (FLAGSET(GetAsyncKeyState(VK_LBUTTON), 0x8000))
  6445. {
  6446. // when user clicks the "+", we get mouse down only after the session
  6447. // is closed, when new session tab is already on X:Y, so dragging
  6448. // starts, prevent that
  6449. if (MilliSecondsBetween(Now(), FSessionsPageControlNewSessionTime) > 500)
  6450. {
  6451. TTerminal * Terminal = reinterpret_cast<TTerminal *>(SessionsPageControl->Pages[Index]->Tag);
  6452. if (Terminal != NULL)
  6453. {
  6454. SessionsPageControl->BeginDrag(false);
  6455. }
  6456. }
  6457. }
  6458. }
  6459. }
  6460. }
  6461. //---------------------------------------------------------------------------
  6462. void __fastcall TCustomScpExplorerForm::SessionsPageControlDragDrop(
  6463. TObject * /*Sender*/, TObject * /*Source*/, int X, int Y)
  6464. {
  6465. int Index = SessionsPageControl->IndexOfTabAt(X, Y);
  6466. // do not allow dropping on the "+" tab
  6467. TTerminal * TargetTerminal = reinterpret_cast<TTerminal *>(SessionsPageControl->Pages[Index]->Tag);
  6468. if ((TargetTerminal != NULL) &&
  6469. (SessionsPageControl->ActivePage->PageIndex != Index))
  6470. {
  6471. Configuration->Usage->Inc(L"SessionTabMoves");
  6472. // this is almost redundant as we would recreate tabs in TerminalListChanged,
  6473. // but we want to actually prevent that to avoid flicker
  6474. SessionsPageControl->ActivePage->PageIndex = Index;
  6475. TTerminal * Terminal = reinterpret_cast<TTerminal *>(SessionsPageControl->ActivePage->Tag);
  6476. TTerminalManager::Instance()->Move(Terminal, TargetTerminal);
  6477. }
  6478. }
  6479. //---------------------------------------------------------------------------
  6480. void __fastcall TCustomScpExplorerForm::SessionsPageControlDragOver(
  6481. TObject * Sender, TObject * Source, int X, int Y,
  6482. TDragState /*State*/, bool & Accept)
  6483. {
  6484. Accept = (Sender == Source);
  6485. if (Accept)
  6486. {
  6487. int Index = SessionsPageControl->IndexOfTabAt(X, Y);
  6488. TTerminal * Terminal = reinterpret_cast<TTerminal *>(SessionsPageControl->Pages[Index]->Tag);
  6489. // do not allow dragging to the "+" tab
  6490. Accept = (Terminal != NULL);
  6491. }
  6492. }
  6493. //---------------------------------------------------------------------------
  6494. void __fastcall TCustomScpExplorerForm::SessionsDDDragOver(int /*KeyState*/,
  6495. const TPoint & Point, int & Effect)
  6496. {
  6497. int Index = SessionsPageControl->IndexOfTabAt(Point.X, Point.Y);
  6498. if (Index < 0)
  6499. {
  6500. Effect = DROPEFFECT_None;
  6501. }
  6502. else
  6503. {
  6504. TTerminal * TargetTerminal = reinterpret_cast<TTerminal *>(SessionsPageControl->Pages[Index]->Tag);
  6505. // do not allow dropping on the "+" tab
  6506. if (TargetTerminal == NULL)
  6507. {
  6508. Effect = DROPEFFECT_None;
  6509. }
  6510. }
  6511. }
  6512. //---------------------------------------------------------------------------
  6513. void __fastcall TCustomScpExplorerForm::SessionsDDProcessDropped(
  6514. TObject * /*Sender*/, int /*KeyState*/, const TPoint & Point, int Effect)
  6515. {
  6516. APPLICATION_EXCEPTION_HACK_BEGIN
  6517. {
  6518. int Index = SessionsPageControl->IndexOfTabAt(Point.X, Point.Y);
  6519. // do not allow dropping on the "+" tab
  6520. TTerminal * TargetTerminal = reinterpret_cast<TTerminal *>(SessionsPageControl->Pages[Index]->Tag);
  6521. if (TargetTerminal != NULL)
  6522. {
  6523. assert(!IsFileControl(DropSourceControl, osRemote));
  6524. if (!IsFileControl(DropSourceControl, osRemote))
  6525. {
  6526. TTerminalManager::Instance()->ActiveTerminal = TargetTerminal;
  6527. RemoteFileControlDragDropFileOperation(SessionsPageControl, Effect,
  6528. TTerminalManager::Instance()->ActiveTerminal->CurrentDirectory);
  6529. }
  6530. }
  6531. }
  6532. APPLICATION_EXCEPTION_HACK_END;
  6533. }
  6534. //---------------------------------------------------------------------------
  6535. void __fastcall TCustomScpExplorerForm::FormClose(TObject * /*Sender*/, TCloseAction & /*Action*/)
  6536. {
  6537. FShowing = false;
  6538. }
  6539. //---------------------------------------------------------------------------
  6540. void __fastcall TCustomScpExplorerForm::RemoteDirViewRead(TObject * /*Sender*/)
  6541. {
  6542. TManagedTerminal * ManagedTerminal =
  6543. dynamic_cast<TManagedTerminal *>(RemoteDirView->Terminal);
  6544. if (ManagedTerminal != NULL)
  6545. {
  6546. ManagedTerminal->DirectoryLoaded = Now();
  6547. }
  6548. }
  6549. //---------------------------------------------------------------------------
  6550. void __fastcall TCustomScpExplorerForm::DirViewSelectItem(TObject * Sender,
  6551. TListItem * /*Item*/, bool /*Selected*/)
  6552. {
  6553. TCustomDirView * DirView = reinterpret_cast<TCustomDirView *>(Sender);
  6554. switch (DirView->LastSelectMethod)
  6555. {
  6556. case smKeyboard:
  6557. Configuration->Usage->Inc(L"KeyboardSelections");
  6558. break;
  6559. case smMouse:
  6560. Configuration->Usage->Inc(L"MouseSelections");
  6561. break;
  6562. }
  6563. }
  6564. //---------------------------------------------------------------------------
  6565. int __fastcall TCustomScpExplorerForm::AddSessionColor(TColor Color)
  6566. {
  6567. if (Color != 0)
  6568. {
  6569. TBitmap * Bitmap = new TBitmap();
  6570. Bitmap->SetSize(FSessionColors->Width, FSessionColors->Height);
  6571. Bitmap->Canvas->Brush->Color = Color;
  6572. Bitmap->Canvas->Brush->Style = bsSolid;
  6573. Bitmap->Canvas->FillRect(TRect(0, 0, FSessionColors->Width, FSessionColors->Height));
  6574. FSessionColors->AddMasked(Bitmap, (TColor)0);
  6575. delete Bitmap;
  6576. return FSessionColors->Count - 1;
  6577. }
  6578. else
  6579. {
  6580. return -1;
  6581. }
  6582. }
  6583. //---------------------------------------------------------------------------
  6584. #pragma warn -8080