CE.cpp 99 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078
  1. // TODO:
  2. // process system headers button
  3. // C++ HEADERS PARSING:
  4. // using namespace;
  5. // EE basic data types to ES types (only in EE headers) ?
  6. // EE headers hide private stuff (after calculating symbols/tokens ?)
  7. // add comments for all builtin keywords (sample usage..)
  8. // C++ generation for Visual Studio
  9. // 0b0011 -> 0x003
  10. // 0x1.1 -> 0...
  11. // 0b0011.1 -> 3.5
  12. // support for custom #define's (make them only global, fix 'preprocess')
  13. // replace
  14. // refactoring
  15. // generation of C++ headers: define global typedefs for nested classes (after "class.h" headers in UNIQUE_NAME+UNIQUE_NAME+"headers.h") "typedef A.AA X;"
  16. // template specialization? (similar mechanism to function overloading? "func_name/817293")
  17. // <TYPE> class X { X(){} }
  18. // < > class X<int> { X(){} } // parsing CTOR will result in error, because creation of X will create X_18273912 (to be unique) and encountering X() will not detect it as the constructor
  19. /******************************************************************************
  20. Font "Lucida Console" should be Sub-Pixel and should contain:
  21. -Ansi, German, French, Polish, Russian, Ellipsis
  22. operators are stored as following names in symbols:
  23. operator= -> "operator="
  24. operator== -> "operator=="
  25. operator+= -> "operator+="
  26. operator() -> "operator()"
  27. operator TYPE -> "operator cast"
  28. operator TYPE2 -> "operator cast"
  29. operator new -> "operator new"
  30. operator delete -> "operator delete"
  31. in short it's:
  32. auto-cast operators as "operator cast"
  33. other operators as "operator?" (? = symbols)
  34. Functions are stored as following names in symbols:
  35. => "func" (function list)
  36. void func( ) .. "func/8917283" (function)
  37. void func(int a) .. "func/7628349" (function)
  38. Labels are stored as:
  39. label: -> "@label" ('@' is added to avoid confusion with other symbols, labels are stored as child of FUNC, and not SPACE)
  40. Symbols with duplicate names are stored as:
  41. "name" // original
  42. "Unique name 1293879" // Unique + name + random value using 'MakeUnique' function
  43. Nameless classes are stored as:
  44. "Nameless 0"
  45. "Nameless 1"
  46. ..
  47. Members of MODIF_TRANSPARENT classes:
  48. class X
  49. {
  50. class // this is the transparent class
  51. {
  52. int x;
  53. }
  54. }
  55. x.full_name -> "X.x" (path/name is set to first non-transparent class, to allow for 'FindChild' to work)
  56. x.parent -> "X.nameless" (parent is set to the transparent class)
  57. All symbols are stored in 'Symbols' counted cache.
  58. 'SymbolDef' is used to store "creator" reference to a 'Symbol' in 'Symbols' (creator increases/decreases 'Symbol::valid')
  59. Symbol::valid indicates if symbol is actually defined (if it's set to zero then it means it's "zombie" symbol, no longer valid)
  60. Handling symbol "pointer array ref" is done in following order:
  61. 1. pointer, 2. array, 3. ref - example - symbol can be a pointer, symbol can be array of pointers, symbol can be reference to array of pointers
  62. Pointers to arrays are processed in following method:
  63. 1. ptr_level, 2. array_dims (those can be both array and pointer) - 1 pointer to array of 3 pointer-pointers "int** (*)x[3]" is handled like this - 'ptr_level'=2 (describes "**"), 'array_dims'={3 (describes "[3]"), DIM_PTR (describes "(*)")}
  64. /******************************************************************************/
  65. #include "stdafx.h"
  66. #if WINDOWS_OLD
  67. #include "../../../ThirdPartyLibs/begin.h"
  68. #define MAXUINT ((UINT)~((UINT)0))
  69. #include "../../../ThirdPartyLibs/VS/Setup.Configuration.h"
  70. #include "../../../ThirdPartyLibs/end.h"
  71. // Use smart pointers (without ATL) to release objects when they fall out of scope.
  72. _COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
  73. _COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
  74. _COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
  75. _COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
  76. _COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
  77. _COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
  78. _COM_SMARTPTR_TYPEDEF(ISetupPackageReference, __uuidof(ISetupPackageReference));
  79. #endif
  80. namespace EE{
  81. namespace Edit{
  82. /******************************************************************************/
  83. #define LOAD_SYMBOLS 1
  84. #define LOG_LINES 16384
  85. /******************************************************************************/
  86. Int TabLength=3;
  87. /******************************************************************************/
  88. Memc<Macro> SystemMacros, // base macros (__cplusplus, _WIN32, ..)
  89. EEMacros, // base macros after including EE libraries
  90. LibMacros, // base macros after including C++ libraries (EE, 3rd party libs)
  91. ProjectMacros; // lib macros with custom project macros
  92. Memc<SymbolPtr> EEUsings, // base using namespaces after including EE libraries
  93. LibUsings, // base using namespaces after including C++ libraries (EE, 3rd party libs)
  94. ProjectUsings; // lib using namespaces with custom project usings
  95. /******************************************************************************/
  96. Keyword NativeKeywords[]=
  97. {
  98. {"using" , true , true , false, false, true, VAR_NONE},
  99. {"namespace", true , true , false, false, true, VAR_NONE},
  100. {"union" , true , true , false, false, true, VAR_NONE},
  101. {"struct" , false, true , false, false, true, VAR_NONE},
  102. {"class" , true , true , false, false, true, VAR_NONE},
  103. {"enum" , true , true , false, false, true, VAR_NONE},
  104. {"typedef" , true , true , false, false, true, VAR_NONE},
  105. {"operator" , true , false, false, false, true, VAR_NONE},
  106. {"public" , true , true , false, true, true, VAR_NONE},
  107. {"private" , true , true , false, true, true, VAR_NONE},
  108. {"protected" , true , true , false, true, true, VAR_NONE},
  109. {"static" , true , true , false, true, true, VAR_NONE},
  110. {"extern" , false, true , false, true, true, VAR_NONE},
  111. {"const" , true , true , false, true, true, VAR_NONE},
  112. {"constexpr" , true , true , false, true, true, VAR_NONE},
  113. {"mutable" , true , true , false, true, true, VAR_NONE},
  114. {"register" , false, true , false, true, true, VAR_NONE},
  115. {"explicit" , true , true , false, true, true, VAR_NONE},
  116. {"virtual" , true , true , false, true, true, VAR_NONE},
  117. {"final" , true , false, false, true, true, VAR_NONE},
  118. {"override" , true , false, false, true, true, VAR_NONE},
  119. {"volatile" , false, true , false, true, true, VAR_NONE},
  120. {"inline" , true , true , false, true, true, VAR_NONE},
  121. {"__forceinline" , false, true , false, true, true, VAR_NONE},
  122. {"friend" , true , true , false, true, true, VAR_NONE},
  123. {"const_mem_addr", true , true , false, true, true, VAR_NONE}, // cpp too because it's used in EE headers
  124. {"switch" , true , false, false, false, true, VAR_NONE},
  125. {"case" , true , true , false, false, true, VAR_NONE},
  126. {"default" , true , false, false, false, true, VAR_NONE},
  127. {"return" , true , true , false, false, true, VAR_NONE},
  128. {"break" , true , false, false, false, true, VAR_NONE},
  129. {"continue", true , false, false, false, true, VAR_NONE},
  130. {"goto" , true , true , false, false, true, VAR_NONE},
  131. {"if" , true , false, false, false, true, VAR_NONE},
  132. {"else" , true , true , false, false, true, VAR_NONE},
  133. {"for" , true , false, false, false, true, VAR_NONE},
  134. {"while" , true , false, false, false, true, VAR_NONE},
  135. {"do" , true , false, false, false, true, VAR_NONE},
  136. {"throw" , false, false, false, false, true, VAR_NONE},
  137. {"try" , false, false, false, false, true, VAR_NONE},
  138. {"catch" , false, false, false, false, true, VAR_NONE},
  139. {"auto" , true, false, true, false, true, VAR_NONE }, // for now just use as typedef
  140. {"void" , true, false, true, false, true, VAR_VOID },
  141. {"bool" , true, false, true, false, true, VAR_BOOL },
  142. {"char" , true, false, true, false, true, VAR_CHAR16},
  143. {"short" , true, false, true, false, true, VAR_SHORT },
  144. {"int" , true, false, true, false, true, VAR_INT },
  145. {"long" , true, false, true, false, true, VAR_LONG },
  146. {"float" , true, false, true, false, true, VAR_NONE }, // this is typedef
  147. {"double", true, false, true, false, true, VAR_NONE }, // this is typedef
  148. { "size_t", false, false, true, false, true, VAR_NONE}, // this is typedef
  149. { "ssize_t", false, false, true, false, true, VAR_NONE}, // this is typedef
  150. { "intptr_t", false, false, true, false, true, VAR_NONE}, // this is typedef
  151. {"uintptr_t", false, false, true, false, true, VAR_NONE}, // this is typedef
  152. {"char16_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  153. {"char32_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  154. {"wchar_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  155. {"__int8" , false, false, true, false, true, VAR_NONE}, // this is typedef
  156. {"__int16" , false, false, true, false, true, VAR_NONE}, // this is typedef
  157. {"__int32" , false, false, true, false, true, VAR_NONE}, // this is typedef
  158. {"__int64" , false, false, true, false, true, VAR_NONE}, // this is typedef
  159. {"int8_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  160. {"uint8_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  161. {"int16_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  162. {"uint16_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  163. {"int32_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  164. {"uint32_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  165. {"int64_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  166. {"uint64_t" , false, false, true, false, true, VAR_NONE}, // this is typedef
  167. {"signed" , false, true, true, false, true, VAR_NONE}, // this is typedef
  168. {"unsigned", false, true, true, false, true, VAR_NONE}, // this is typedef
  169. {"template", true, false, false, false, true, VAR_NONE},
  170. {"typename", true, true , false, false, true, VAR_NONE},
  171. {"sizeof", true, false, false, false, true, VAR_NONE},
  172. {"typeid", true, false, false, false, true, VAR_NONE},
  173. {"dynamic_cast" , true, false, false, false, true, VAR_NONE},
  174. {"static_cast" , true, false, false, false, true, VAR_NONE},
  175. {"const_cast" , true, false, false, false, true, VAR_NONE},
  176. {"reinterpret_cast", true, false, false, false, true, VAR_NONE},
  177. {"__super", false, false, false, false, true, VAR_NONE},
  178. {"this" , true , false, false, false, true, VAR_NONE},
  179. {"true" , true, false, false, false, true, VAR_BOOL},
  180. {"false", true, false, false, false, true, VAR_BOOL},
  181. {"new" , true, true, false, false, true, VAR_NONE},
  182. {"delete", true, true, false, false, true, VAR_NONE},
  183. {"__cdecl" , false, true, false, true, true, VAR_NONE},
  184. {"__stdcall" , false, true, false, true, true, VAR_NONE},
  185. {"__fastcall", false, true, false, true, true, VAR_NONE},
  186. {"__thiscall", false, true, false, true, true, VAR_NONE},
  187. {"__declspec", false, true, false, false, true, VAR_NONE},
  188. // c# / es
  189. //{"base" , true, false, false, false, false, VAR_NONE},
  190. {"super", true, false, false, false, false, VAR_NONE},
  191. //{"str" , true, false, true, false, false, VAR_NONE},
  192. //{"string", true, false, true, false, false, VAR_NONE},
  193. { "byte" , true, false, true, false, false, VAR_BYTE },
  194. {"sbyte" , true, false, true, false, false, VAR_SBYTE },
  195. {"ushort" , true, false, true, false, false, VAR_USHORT},
  196. {"uint" , true, false, true, false, false, VAR_UINT },
  197. { "intptr", true, false, true, false, false, VAR_NONE }, // this is a typedef
  198. {"uintptr", true, false, true, false, false, VAR_NONE }, // this is a typedef
  199. {"ulong" , true, false, true, false, false, VAR_ULONG },
  200. {"flt" , true, false, true, false, false, VAR_FLT },
  201. {"dbl" , true, false, true, false, false, VAR_DBL },
  202. { "ptr" , true, false, true, false, false, VAR_NONE }, // this is a typedef
  203. {"cptr" , true, false, true, false, false, VAR_NONE }, // this is a typedef
  204. { "char8" , true, false, true, false, false, VAR_CHAR8 },
  205. {"cchar8" , true, false, true, false, false, VAR_NONE }, // this is a typedef
  206. {"cchar" , true, false, true, false, false, VAR_NONE }, // this is a typedef
  207. //{"until", true, false, false, false, false, VAR_NONE},
  208. {"null_t", false, false, true , false, false, VAR_NULL},
  209. {"null" , true , false, false, false, false, VAR_NULL},
  210. };
  211. const Int NativeKeywordsElms=Elms(NativeKeywords);
  212. Str PreprocKeywords[]=
  213. {
  214. "include",
  215. "if",
  216. "ifdef",
  217. "ifndef",
  218. "elif",
  219. "else",
  220. "endif",
  221. "undef",
  222. "define",
  223. "defined",
  224. "pack",
  225. "pragma",
  226. "error",
  227. };
  228. const Int PreprocKeywordsElms=Elms(PreprocKeywords);
  229. static Memc<SymbolDef> SymbolDefs; // built-in keywords
  230. Bool CppMode;
  231. CodeEditor CE;
  232. static CChar8 *CodeEditorDat="Bin/Code Editor.dat";
  233. CChar8 *AutoSource ="Auto.h";
  234. /******************************************************************************/
  235. // GLOBAL
  236. /******************************************************************************/
  237. Int TypeSize(VAR_TYPE type)
  238. {
  239. switch(type) // now check if it has raw value
  240. {
  241. default : return 0; // VAR_NONE
  242. case VAR_VOID : return 0;
  243. case VAR_BOOL : return 1;
  244. case VAR_BYTE : return 1;
  245. case VAR_SBYTE : return 1;
  246. case VAR_SHORT : return 2;
  247. case VAR_USHORT: return 2;
  248. case VAR_INT : return 4;
  249. case VAR_UINT : return 4;
  250. case VAR_LONG : return 8;
  251. case VAR_ULONG : return 8;
  252. case VAR_FLT : return 4;
  253. case VAR_DBL : return 8;
  254. case VAR_CHAR8 : return 1;
  255. case VAR_CHAR16: return 2;
  256. case VAR_ENUM : return EnumSize;
  257. case VAR_NULL : return PtrSize;
  258. }
  259. }
  260. Str TypeName(VAR_TYPE type)
  261. {
  262. switch(type)
  263. {
  264. default : return "none"; // VAR_NONE
  265. case VAR_VOID : return "void";
  266. case VAR_BOOL : return "bool";
  267. case VAR_BYTE : return "byte";
  268. case VAR_SBYTE : return "sbyte";
  269. case VAR_SHORT : return "short";
  270. case VAR_USHORT: return "ushort";
  271. case VAR_INT : return "int";
  272. case VAR_UINT : return "uint";
  273. case VAR_LONG : return "long";
  274. case VAR_ULONG : return "ulong";
  275. case VAR_FLT : return "flt";
  276. case VAR_DBL : return "dbl";
  277. case VAR_CHAR8 : return "char8";
  278. case VAR_CHAR16: return "char";
  279. case VAR_ENUM : return "enum";
  280. case VAR_NULL : return "null";
  281. }
  282. }
  283. Symbol* TypeSymbol(VAR_TYPE type)
  284. {
  285. switch(type)
  286. {
  287. case VAR_VOID :
  288. case VAR_BOOL :
  289. case VAR_BYTE :
  290. case VAR_SBYTE :
  291. case VAR_SHORT :
  292. case VAR_USHORT:
  293. case VAR_INT :
  294. case VAR_UINT :
  295. case VAR_LONG :
  296. case VAR_ULONG :
  297. case VAR_FLT :
  298. case VAR_DBL :
  299. case VAR_CHAR8 :
  300. case VAR_CHAR16:
  301. case VAR_NULL : return Symbols(TypeName(type));
  302. default : return null;
  303. }
  304. }
  305. VAR_TYPE SameSizeType(VAR_TYPE type)
  306. {
  307. switch(type)
  308. {
  309. case VAR_BOOL :
  310. case VAR_CHAR8:
  311. case VAR_SBYTE: return VAR_BYTE;
  312. case VAR_CHAR16:
  313. case VAR_USHORT: return VAR_SHORT;
  314. case VAR_ENUM:
  315. case VAR_UINT: return VAR_INT;
  316. case VAR_ULONG: return VAR_LONG;
  317. default: return type;
  318. }
  319. }
  320. VAR_TYPE SameSizeSignType(VAR_TYPE type)
  321. {
  322. switch(type)
  323. {
  324. case VAR_BOOL :
  325. case VAR_CHAR8: return VAR_BYTE;
  326. case VAR_CHAR16: return VAR_USHORT;
  327. case VAR_ENUM: return VAR_INT;
  328. default: return type;
  329. }
  330. }
  331. VAR_TYPE SameSizeSignBoolType(VAR_TYPE type)
  332. {
  333. switch(type)
  334. {
  335. case VAR_CHAR8: return VAR_BYTE;
  336. case VAR_CHAR16: return VAR_USHORT;
  337. case VAR_ENUM: return VAR_INT;
  338. default: return type;
  339. }
  340. }
  341. VAR_TYPE ComplementResult(VAR_TYPE type)
  342. {
  343. switch(type)
  344. {
  345. case VAR_CHAR8 :
  346. case VAR_CHAR16:
  347. case VAR_BOOL :
  348. case VAR_BYTE :
  349. case VAR_SBYTE :
  350. case VAR_SHORT :
  351. case VAR_USHORT:
  352. case VAR_INT :
  353. case VAR_ENUM : return VAR_INT;
  354. case VAR_UINT : return VAR_UINT;
  355. case VAR_LONG : return VAR_LONG;
  356. case VAR_ULONG : return VAR_ULONG;
  357. default: return VAR_NONE;
  358. }
  359. }
  360. VAR_TYPE NegativeResult(VAR_TYPE type)
  361. {
  362. switch(type)
  363. {
  364. case VAR_CHAR8 :
  365. case VAR_CHAR16:
  366. case VAR_BOOL :
  367. case VAR_BYTE :
  368. case VAR_SBYTE :
  369. case VAR_SHORT :
  370. case VAR_USHORT:
  371. case VAR_INT :
  372. case VAR_UINT :
  373. case VAR_ENUM : return VAR_INT;
  374. case VAR_LONG :
  375. case VAR_ULONG : return VAR_LONG;
  376. case VAR_FLT: return VAR_FLT;
  377. case VAR_DBL: return VAR_DBL;
  378. default: return VAR_NONE;
  379. }
  380. }
  381. // in C++ (int op int)->int, (uint op int)->uint, (int op uint)->uint, (uint op uint)->uint (uint has higher preference, int is choosed only if both are int)
  382. VAR_TYPE MulResult(VAR_TYPE a, VAR_TYPE b)
  383. {
  384. if(a==VAR_NONE || a==VAR_VOID || a==VAR_NULL || b==VAR_NONE || b==VAR_VOID || b==VAR_NULL)return VAR_NONE;
  385. if(a==VAR_DBL || b==VAR_DBL )return VAR_DBL;
  386. if(a==VAR_FLT || b==VAR_FLT )return VAR_FLT;
  387. if(a==VAR_BOOL && b==VAR_BOOL)return VAR_BOOL;
  388. if(a==VAR_LONG || a==VAR_ULONG || b==VAR_LONG || b==VAR_ULONG)return (SignedType(a) && SignedType(b)) ? VAR_LONG : VAR_ULONG;
  389. return (SignedType(a) && SignedType(b)) ? VAR_INT : VAR_UINT ;
  390. }
  391. VAR_TYPE DivResult(VAR_TYPE a, VAR_TYPE b)
  392. {
  393. if(a==VAR_NONE || a==VAR_VOID || a==VAR_NULL || b==VAR_NONE || b==VAR_VOID || b==VAR_NULL)return VAR_NONE;
  394. if(a==VAR_DBL || b==VAR_DBL )return VAR_DBL;
  395. if(a==VAR_FLT || b==VAR_FLT )return VAR_FLT;
  396. if(a==VAR_LONG || a==VAR_ULONG)return (SignedType(a) && SignedType(b)) ? VAR_LONG : VAR_ULONG;
  397. return (SignedType(a) && SignedType(b)) ? VAR_INT : VAR_UINT ;
  398. }
  399. VAR_TYPE ModResult(VAR_TYPE a, VAR_TYPE b)
  400. {
  401. if(a==VAR_NONE || a==VAR_VOID || a==VAR_NULL || b==VAR_NONE || b==VAR_VOID || b==VAR_NULL || RealType(a) || RealType(b))return VAR_NONE;
  402. if(a==VAR_LONG || a==VAR_ULONG)return (SignedType(a) && SignedType(b)) ? VAR_LONG : VAR_ULONG;
  403. return (SignedType(a) && SignedType(b)) ? VAR_INT : VAR_UINT ;
  404. }
  405. VAR_TYPE AddResult(VAR_TYPE a, VAR_TYPE b)
  406. {
  407. if(a==VAR_NONE || a==VAR_VOID || a==VAR_NULL || b==VAR_NONE || b==VAR_VOID || b==VAR_NULL)return VAR_NONE;
  408. if(a==VAR_DBL || b==VAR_DBL)return VAR_DBL;
  409. if(a==VAR_FLT || b==VAR_FLT)return VAR_FLT;
  410. if(a==VAR_LONG || a==VAR_ULONG || b==VAR_LONG || b==VAR_ULONG)return (SignedType(a) && SignedType(b)) ? VAR_LONG : VAR_ULONG;
  411. return (SignedType(a) && SignedType(b)) ? VAR_INT : VAR_UINT ;
  412. }
  413. VAR_TYPE SubResult(VAR_TYPE a, VAR_TYPE b)
  414. {
  415. if(a==VAR_NONE || a==VAR_VOID || a==VAR_NULL || b==VAR_NONE || b==VAR_VOID || b==VAR_NULL)return VAR_NONE;
  416. if(a==VAR_DBL || b==VAR_DBL)return VAR_DBL;
  417. if(a==VAR_FLT || b==VAR_FLT)return VAR_FLT;
  418. if(a==VAR_LONG || a==VAR_ULONG || b==VAR_LONG || b==VAR_ULONG)return VAR_LONG;
  419. return VAR_INT ;
  420. }
  421. VAR_TYPE ShiftLeftResult(VAR_TYPE a, VAR_TYPE b)
  422. {
  423. if(a==VAR_NONE || a==VAR_VOID || a==VAR_NULL || b==VAR_NONE || b==VAR_VOID || b==VAR_NULL || RealType(a) || RealType(b))return VAR_NONE;
  424. if(a==VAR_LONG || a==VAR_ULONG)return SignedType(a) ? VAR_LONG : VAR_ULONG; // in C++ "Int<<Int64" is still an Int
  425. return SignedType(a) ? VAR_INT : VAR_UINT ;
  426. }
  427. VAR_TYPE ShiftRightResult(VAR_TYPE a, VAR_TYPE b)
  428. {
  429. if(a==VAR_NONE || a==VAR_VOID || a==VAR_NULL || b==VAR_NONE || b==VAR_VOID || b==VAR_NULL || RealType(a) || RealType(b))return VAR_NONE;
  430. if(a==VAR_BOOL && b==VAR_BOOL )return VAR_BOOL;
  431. if(a==VAR_LONG || a==VAR_ULONG)return SignedType(a) ? VAR_LONG : VAR_ULONG;
  432. return SignedType(a) ? VAR_INT : VAR_UINT ;
  433. }
  434. VAR_TYPE BitResult(VAR_TYPE a, VAR_TYPE b)
  435. {
  436. if(a==VAR_NONE || a==VAR_VOID || a==VAR_NULL || b==VAR_NONE || b==VAR_VOID || b==VAR_NULL || RealType(a) || RealType(b))return VAR_NONE;
  437. if(a==VAR_LONG || a==VAR_ULONG || b==VAR_LONG || b==VAR_ULONG)return (SignedType(a) && SignedType(b)) ? VAR_LONG : VAR_ULONG;
  438. return (SignedType(a) && SignedType(b)) ? VAR_INT : VAR_UINT ;
  439. }
  440. /******************************************************************************/
  441. Bool LostConst(UInt src_const_level, UInt dest_const_level)
  442. {
  443. // src dest lost
  444. // 0 0 0
  445. // 0 1 0
  446. // 1 0 1
  447. // 1 1 0
  448. UInt lost=(src_const_level & ~dest_const_level);
  449. return lost!=0;
  450. }
  451. /******************************************************************************/
  452. Int AlignAddress(Int address, Int size)
  453. {
  454. if(size>=2)switch(size)
  455. {
  456. case 2:
  457. case 3: return Ceil2(address);
  458. case 4:
  459. case 5:
  460. case 6:
  461. case 7: return Ceil4(address);
  462. default: return Ceil8(address);
  463. }
  464. return address;
  465. }
  466. /******************************************************************************/
  467. Bool SourceExt(C Str &ext)
  468. {
  469. return ext=="h"
  470. || ext=="hpp"
  471. || ext=="cpp"
  472. || ext=="c"
  473. || ext=="cc"
  474. || ext=="cxx"
  475. || ext=="inc" // include c file
  476. || ext=="m" // Apple Objective-C
  477. || ext=="mm"; // Apple Objective-C++
  478. }
  479. Bool TextExt(C Str &ext)
  480. {
  481. return SourceExt(ext)
  482. || ext=="cs" // C#
  483. || ext=="java"
  484. || ext=="txt"
  485. || ext=="xml"
  486. || ext=="htm"
  487. || ext=="html"
  488. || ext=="php"
  489. || ext=="mk";
  490. }
  491. Bool AllowedExt(C Str &ext)
  492. {
  493. return TextExt(ext)
  494. || ext=="lib"
  495. || ext=="ico"
  496. || ext=="pak";
  497. }
  498. /******************************************************************************/
  499. Memc<Str> GetFiles(C Str &files)
  500. {
  501. Memc<Str> elms; Split(elms, files, '|'); REPA(elms)
  502. {
  503. Str &s=elms[i];
  504. s.removeOuterWhiteChars().replace('\\', '/');
  505. if(!s.is())elms.remove(i, true);
  506. }
  507. return elms;
  508. }
  509. /******************************************************************************/
  510. // MENU
  511. /******************************************************************************/
  512. static void MenuNew ( ) {CE.New ();}
  513. static void MenuOverwrite( ) {CE.overwrite();}
  514. static void MenuSave ( ) {CE.save ();}
  515. static void MenuLoad ( ) {CE.load ();}
  516. static void MenuClose (Ptr) {CE.close ();}
  517. static void MenuLocate ( ) {CE.cei().elmLocate(CE.cei().sourceCurId());}
  518. static void EditUndo ( ) { CE.undo ();}
  519. static void EditRedo ( ) { CE.redo ();}
  520. static void EditCut ( ) {if(!CE.view_mode())CE.cut ();}
  521. static void EditCopy ( ) {if(!CE.view_mode())CE.copy ();}
  522. static void EditPaste ( ) {if(!CE.view_mode())CE.paste ();}
  523. static void EditPaste2 ( ) {if(!CE.view_mode())CE.paste (false);}
  524. static void EditSeparator ( ) {if(!CE.view_mode())CE.separator ();}
  525. static void EditSelectAll ( ) {if(!CE.view_mode())CE.selectAll ();}
  526. static void EditSelectWord ( ) {if(!CE.view_mode())CE.selectWord();}
  527. static void EditMakeLower ( ) {if(!CE.view_mode())CE.makeCase (false);}
  528. static void EditMakeUpper ( ) {if(!CE.view_mode())CE.makeCase (true );}
  529. static void EditFind (Ptr) {CE.find .toggle();}
  530. static void EditReplace (Ptr) {CE.replace.visibleToggleActivate();}
  531. static void EditGotoLine ( ) {CE.goto_line_window.visibleToggleActivate();}
  532. static void EditGotoDef ( ) {if(CE.cur())CE.cur()->jumpToCur ();}
  533. static void EditFindRef ( ) {if(CE.cur())CE.cur()->findAllReferences();}
  534. static void EditPrevIssue ( ) {CE.prevIssue();}
  535. static void EditNextIssue ( ) {CE.nextIssue();}
  536. static void EditPrevCurPos ( ) {CE.prevCurPos();}
  537. static void EditNextCurPos ( ) {CE.nextCurPos();}
  538. static void EditAutoComplete( ) {if(CE.cur())CE.cur()->listSuggestions( 1);}
  539. static void EditAutoCompleteElm() {if(CE.cur())CE.cur()->listSuggestions(-2);}
  540. static void EditNextFile() {CE.nextFile();}
  541. static void EditPrevFile() {CE.prevFile();}
  542. static void ViewMode() {CE.view_mode.push();}
  543. static void ElmNames() {CE.view_what.menu("Element Names" , !CE.view_what.menu("Element Names" ));}
  544. static void FuncBody() {CE.view_what.menu("Function Bodies", !CE.view_what.menu("Function Bodies"));}
  545. /******************************************************************************/
  546. // CODE EDITOR
  547. /******************************************************************************/
  548. static CChar8 *ExcludeHeaders[]=
  549. {
  550. "begin.h",
  551. "end.h",
  552. "Structs.h",
  553. "Vertex Index Buffer Ex.h",
  554. "_Cache.h",
  555. "_Map.h",
  556. "_Memc.h",
  557. "_Memc Thread Safe.h",
  558. "_Memb.h",
  559. "_Memx.h",
  560. "_Meml.h",
  561. "_Grid.h",
  562. "Templates.h",
  563. "Index.h",
  564. "Display Viewport.h",
  565. "Fur.h",
  566. "Renderer Instancing.h",
  567. "Shader Main.h",
  568. "Sound Buffer.h",
  569. "Aggregate.h",
  570. "Android.h",
  571. "String Borrowed.h",
  572. "Esenthel Config.h",
  573. "MP4.h",
  574. };
  575. /*static CChar8 *ReplaceHeaders[][2]=
  576. {
  577. "animation keys.h", "_/Animation",
  578. "quaternion.h", "_/Math",
  579. "grid.h", "_/Memory",
  580. "mem list.h", "_/Memory",
  581. "Mem Continuous Thread Safe.h", "_/Memory",
  582. "mesh group.h", "_/Mesh",
  583. "mesh import.h", "_/Mesh",
  584. "mesh render.h", "_/Mesh",
  585. //"string borrowed.h", "_/Misc",
  586. "thread.h", "_/Misc",
  587. "windows.h", "_/Misc",
  588. "socket.h", "_/Net",
  589. "Editor Interface.h", "_/Edit",
  590. "Undo.h", "_/Edit",
  591. "Version.h", "_/Edit",
  592. "Viewport4.h", "_/Edit",
  593. };*/
  594. static FILE_LIST_MODE AddEEHeader(C FileFind &ff, CodeEditor &ce)
  595. {
  596. if(ff.type==FSTD_FILE)
  597. {
  598. Str relative_path=SkipStartPath(ff.pathName(), ce.ee_h_path),
  599. target_path=relative_path,
  600. base=ff.name;
  601. REPA(ExcludeHeaders)if(base==ExcludeHeaders[i] )return FILE_LIST_CONTINUE;
  602. //REPA(ReplaceHeaders)if(base==ReplaceHeaders[i][0]){target_path=S+ReplaceHeaders[i][1]+'\\'+base; break;}
  603. if(StartsPath(target_path, "Code"))return FILE_LIST_CONTINUE; // skip all from "Code" folders
  604. GetFile(ce.items, GetExtNot(target_path), ff.pathName()); // add folder & file to items
  605. }
  606. return FILE_LIST_CONTINUE;
  607. }
  608. /******************************************************************************/
  609. void CodeEditor::setMenu(Node<MenuElm> &menu)
  610. {
  611. {
  612. {
  613. Node<MenuElm> &f=menu+="File";
  614. /*f.New().create("New" , MenuNew ).kbsc(KbSc(KB_N, KBSC_CTRL_CMD));
  615. f++;*/
  616. f.New().create("Save" , MenuOverwrite).kbsc(KbSc(KB_F2 )).kbsc2(KbSc(KB_S, KBSC_CTRL_CMD ));
  617. /*f.New().create("Save" , MenuSave ).kbsc(KbSc(KB_F2, KBSC_CTRL_CMD)).kbsc2(KbSc(KB_S, KBSC_CTRL_CMD|KBSC_SHIFT));
  618. f++;
  619. f.New().create("Load" , MenuLoad ).kbsc(KbSc(KB_F3 )).kbsc2(KbSc(KB_O, KBSC_CTRL_CMD));*/
  620. f.New().create("Close" , MenuClose ).kbsc(KbSc(KB_F3, KBSC_ALT|KBSC_REPEAT)).kbsc2(KbSc('q' , KBSC_CTRL_CMD|KBSC_REPEAT));
  621. f.New().create("Locate" , MenuLocate ).kbsc(KbSc(KB_L , KBSC_CTRL_CMD )).desc("Locate this file in the Project");
  622. }
  623. {
  624. Node<MenuElm> &e=menu+="Edit";
  625. e.New().create("Undo" , EditUndo).kbsc(KbSc(KB_Z, KBSC_CTRL_CMD|KBSC_REPEAT));
  626. e.New().create("Redo" , EditRedo).kbsc(KbSc(KB_Y, KBSC_CTRL_CMD|KBSC_REPEAT)).kbsc2(KbSc(KB_Z, KBSC_CTRL_CMD|KBSC_SHIFT|KBSC_REPEAT));
  627. e.New().create("Undo2", EditUndo).kbsc(KbSc(KB_BACK, KBSC_ALT |KBSC_REPEAT)).flag(MENU_HIDDEN); // keep those hidden because they occupy too much of visible space (besides on Windows Notepad they also work and are not listed)
  628. e.New().create("Redo2", EditRedo).kbsc(KbSc(KB_BACK, KBSC_ALT|KBSC_SHIFT|KBSC_REPEAT)).flag(MENU_HIDDEN); // keep those hidden because they occupy too much of visible space (besides on Windows Notepad they also work and are not listed)
  629. e++;
  630. e.New().create("Cut" , EditCut ).kbsc(KbSc('x', KBSC_CTRL_CMD|KBSC_REPEAT));
  631. e.New().create("Copy" , EditCopy ).kbsc(KbSc('c', KBSC_CTRL_CMD|KBSC_REPEAT));
  632. e.New().create("Paste" , EditPaste ).kbsc(KbSc('v', KBSC_CTRL_CMD|KBSC_REPEAT));
  633. e.New().create("Paste Don't Move Cursor", EditPaste2).kbsc(KbSc('V', KBSC_CTRL_CMD|KBSC_REPEAT)).desc("This option performs Paste without moving the cursor");
  634. e++;
  635. e.New().create("Insert Separator", EditSeparator).kbsc(KbSc(KB_ENTER, KBSC_CTRL_CMD|KBSC_SHIFT|KBSC_REPEAT));
  636. e++;
  637. e.New().create("Select All" , EditSelectAll ).kbsc(KbSc('a', KBSC_CTRL_CMD));
  638. e.New().create("Select Word", EditSelectWord).kbsc(KbSc('w', KBSC_CTRL_CMD));
  639. e++;
  640. e.New().create("Find" , EditFind ).kbsc(KbSc('f', KBSC_CTRL_CMD));
  641. e.New().create("Find Next" , FindNext, find).kbsc(KbSc('d', KBSC_CTRL_CMD|KBSC_REPEAT));
  642. e.New().create("Find Previous", FindPrev, find).kbsc(KbSc('D', KBSC_CTRL_CMD|KBSC_REPEAT));
  643. e.New().create("Replace" , EditReplace ).kbsc(KbSc('r', KBSC_CTRL_CMD));
  644. e++;
  645. e.New().create("Next Opened File" , EditNextFile).kbsc(KbSc(KB_F6, KBSC_REPEAT)).kbsc2(KbSc(KB_TAB, KBSC_CTRL_CMD |KBSC_REPEAT));
  646. e.New().create("Previous Opened File", EditPrevFile).kbsc(KbSc(KB_F6, KBSC_SHIFT|KBSC_REPEAT)).kbsc2(KbSc(KB_TAB, KBSC_CTRL_CMD|KBSC_SHIFT|KBSC_REPEAT));
  647. e++;
  648. e.New().create("Next Issue" , EditNextIssue).kbsc(KbSc('e', KBSC_CTRL_CMD|KBSC_REPEAT)).desc("Go to the next compiler issue");
  649. e.New().create("Previous Issue", EditPrevIssue).kbsc(KbSc('E', KBSC_CTRL_CMD|KBSC_REPEAT)).desc("Go to the previous compiler issue");
  650. e++;
  651. e.New().create("Navigate Forward" , EditNextCurPos).kbsc(KbSc(KB_RIGHT, KBSC_ALT|KBSC_REPEAT)).kbsc2(KbSc(KB_RBR, KBSC_CTRL_CMD|KBSC_REPEAT));
  652. e.New().create("Navigate Backward" , EditPrevCurPos).kbsc(KbSc(KB_LEFT , KBSC_ALT|KBSC_REPEAT)).kbsc2(KbSc(KB_LBR, KBSC_CTRL_CMD|KBSC_REPEAT));
  653. e.New().create("Navigate Forward2" , EditNextCurPos).kbsc(KbSc(KB_NAV_FORWARD, KBSC_REPEAT)).flag(MENU_HIDDEN);
  654. e.New().create("Navigate Backward2", EditPrevCurPos).kbsc(KbSc(KB_NAV_BACK , KBSC_REPEAT)).flag(MENU_HIDDEN);
  655. e++;
  656. e.New().create("Auto Complete (for Code Symbols)" , EditAutoComplete ).kbsc(KbSc(KB_SPACE, KBSC_CTRL_CMD));
  657. e.New().create("Auto Complete (for Project Elements)", EditAutoCompleteElm).kbsc(KbSc(KB_SPACE, KBSC_CTRL_CMD|KBSC_SHIFT));
  658. e++;
  659. e.New().create("Go To Line", EditGotoLine).kbsc(KbSc('g', KBSC_CTRL_CMD));
  660. e.New().create("Go To Definition" , EditGotoDef).kbsc(KbSc(KB_ENTER, KBSC_CTRL_CMD )).desc("Go to definition of the symbol located at cursor position.\nAlternative shortcut for this option is Middle Mouse Button or Ctrl + Left Mouse Button.");
  661. e.New().create("Find All References", EditFindRef).kbsc(KbSc(KB_ENTER, KBSC_CTRL_CMD|KBSC_ALT)).desc("Find all references of the symbol located at cursor position.\nAlternative shortcut for this option is Ctrl + Middle Mouse Button.");
  662. e++;
  663. e.New().create("Make Lowercase", EditMakeLower).kbsc(KbSc('u', KBSC_CTRL_CMD|KBSC_REPEAT));
  664. e.New().create("Make Uppercase", EditMakeUpper).kbsc(KbSc('U', KBSC_CTRL_CMD|KBSC_REPEAT));
  665. e.New().create("Elm Names" , ElmNames).kbsc(KbSc(KB_E, KBSC_ALT)).flag(MENU_HIDDEN);
  666. e.New().create("View Mode" , ViewMode).kbsc(KbSc(KB_V, KBSC_ALT)).flag(MENU_HIDDEN);
  667. e.New().create("Func Bodies", FuncBody).kbsc(KbSc(KB_B, KBSC_ALT)).flag(MENU_HIDDEN);
  668. }
  669. }
  670. }
  671. /******************************************************************************/
  672. static void BuildClose (CodeEditor &ce) {ce.visibleOutput (false);}
  673. static void DevlogClose (CodeEditor &ce) {ce.visibleAndroidDevLog(false);}
  674. static void OutputExport (CodeEditor &ce) {ce. build_io.save();}
  675. static void DevlogExport (CodeEditor &ce) {ce.devlog_io.save();}
  676. static void DevlogClear (CodeEditor &ce) {ce.devlog_data.clear(); ce.devlog_list.clear();}
  677. static void RefreshSourceLines(CodeEditor &ce)
  678. {
  679. //ce.func_bodies .visible(ce.view_mode());
  680. //ce.private_members.visible(ce.view_mode());
  681. if(ce.cur())ce.cur()->validateView();
  682. }
  683. static void OutputCopy(CodeEditor &ce)
  684. {
  685. Str text; FREPA(ce.build_list)if(CodeEditor::BuildResult *line=ce.build_list.visToData(i)){text+=line->text; text+='\n';}
  686. ClipSet(text);
  687. }
  688. static void ViewElmNames () {CE.view_elm_names =CE.view_what.menu("Element Names" );}
  689. static void ViewComments () {CE.view_comments =CE.view_what.menu("Comments" ); RefreshSourceLines(CE);}
  690. static void ViewFuncs () {CE.view_funcs =CE.view_what.menu("Functions" ); RefreshSourceLines(CE);}
  691. static void ViewFuncBodies () {CE.view_func_bodies =CE.view_what.menu("Function Bodies"); RefreshSourceLines(CE);}
  692. static void ViewPrivateMembers() {CE.view_private_members=CE.view_what.menu("Private Members"); RefreshSourceLines(CE);}
  693. static void OutputExport(C Str &name, CodeEditor &ce)
  694. {
  695. FileText ft; if(ft.write(name))FREPA(ce.build_list)if(CodeEditor::BuildResult *line=ce.build_list.visToData(i))ft.putLine(line->text);
  696. }
  697. static void DevlogExport(C Str &name, CodeEditor &ce)
  698. {
  699. FileText ft; if(ft.write(name))FREPA(ce.devlog_list)if(CodeEditor::DeviceLog *dl=ce.devlog_list.visToData(i))ft.putLine(dl->asText());
  700. }
  701. static void DevlogFilter(CodeEditor &ce)
  702. {
  703. Memt <Bool> visible;
  704. MemPtr<Bool> v;
  705. if(ce.devlog_filter())
  706. {
  707. v.point(visible.setNum(ce.devlog_data.elms()));
  708. REPAO(visible)=(ce.devlog_data[i].mode==CodeEditor::DeviceLog::APP);
  709. }
  710. ce.devlog_list.setData(ce.devlog_data, v, true);
  711. }
  712. static void DevlogFilter2(CodeEditor &ce) {DevlogFilter(ce); ce.devlog_region.scrollEndY(true);}
  713. static Str DeviceLogOrder(C CodeEditor::DeviceLog &dl) {return TextInt(CE.devlog_data.index(&dl), 5);}
  714. static void BuildError(C Str &msg, Bool at_end)
  715. {
  716. CE.buildNew().set(msg).setError();
  717. CE.buildUpdate(false);
  718. if(at_end)CE.build_region.scrollEndY(); // auto-scroll to the end
  719. }
  720. static Int CompareItem(C Item &a, C Item &b)
  721. {
  722. if(Int c=Compare(a.type , b.type ))return c;
  723. if(Int c=Compare(a.base_name, b.base_name))return c;
  724. return 0;
  725. }
  726. static void SortItems(Memx<Item> &items)
  727. {
  728. items.sort(CompareItem); REPA(items)SortItems(items[i].children);
  729. }
  730. /******************************************************************************/
  731. CodeEditor::CodeEditor()
  732. {
  733. _cur=null;
  734. view_elm_names=view_comments=view_funcs=true; view_func_bodies=view_private_members=false;
  735. devenv_version=-1; devenv_express=devenv_com=build_msbuild=false;
  736. build_mode=BUILD_BUILD; build_exe_type=EXE_EXE; build_debug=true; build_windows_code_sign=false; build_phase=build_phases=build_step=build_steps=0; build_refresh=0; build_project_id.zero();
  737. curposi=0;
  738. symbols_loaded=false;
  739. menu_on_top=false;
  740. config_debug=true; config_dx9=false; config_32_bit=false;
  741. cei(cei_temp);
  742. parent=null;
  743. #if MAC
  744. config_exe=EXE_MAC;
  745. #elif LINUX
  746. config_exe=EXE_LINUX;
  747. #else
  748. config_exe=EXE_EXE;
  749. #endif
  750. }
  751. void CodeEditor::del()
  752. {
  753. sources .del(); // delete before 'Symbols' container
  754. SymbolDefs.del(); // delete before 'Symbols' container
  755. items .del();
  756. }
  757. /******************************************************************************/
  758. void CodeEditor::replacePath(C Str &src, C Str &dest)
  759. {
  760. REPAO(items ).replacePath(src, dest);
  761. REPAO(sources).replacePath(src, dest);
  762. }
  763. /******************************************************************************/
  764. void CodeEditor::create(GuiObj *parent, Bool menu_on_top)
  765. {
  766. T.parent =parent;
  767. T.menu_on_top=menu_on_top;
  768. Symbols.caseSensitive(true);
  769. // setup keywords
  770. Sort( NativeKeywords, Elms( NativeKeywords), CompareCS);
  771. Sort(PreprocKeywords, Elms(PreprocKeywords), CompareCS);
  772. FREPA(NativeKeywords)
  773. {
  774. Keyword &k=NativeKeywords[i];
  775. SymbolDef &s=SymbolDefs.New().require(k.name);
  776. s->type =Symbol::KEYWORD;
  777. s->var_type =k.var_type;
  778. FlagSet(s->modifiers, Symbol::MODIF_DATA_TYPE , k.data_type );
  779. FlagSet(s->modifiers, Symbol::MODIF_ES_ONLY , !k.cpp );
  780. FlagSet(s->modifiers, Symbol::MODIF_CPP_MODIFIER , k.is_modifier );
  781. FlagSet(s->modifiers, Symbol::MODIF_FOLLOW_BY_SPACE , k.follow_by_space );
  782. FlagSet(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS, !k.use_for_suggestions);
  783. }
  784. Symbol::TYPE typedef_type=Symbol::KEYWORD; // keep as keywords so "Find" displays them as KEYWORD's and 'isMemberOf' and 'canBeAccessedFrom' treat them as keywords
  785. {Symbol &s=*Symbols("auto" ); s.type=typedef_type; s.value="void" ;}
  786. {Symbol &s=*Symbols( "ptr" ); s.type=typedef_type; s.value="void" ; s.value.const_level=0; s.value.ptr_level=1;}
  787. {Symbol &s=*Symbols("cptr" ); s.type=typedef_type; s.value="void" ; s.value.const_level=1; s.value.ptr_level=1;}
  788. {Symbol &s=*Symbols("cchar8" ); s.type=typedef_type; s.value="char8" ; s.value.const_level=1; s.value.ptr_level=0;}
  789. {Symbol &s=*Symbols("cchar" ); s.type=typedef_type; s.value="char" ; s.value.const_level=1; s.value.ptr_level=0;}
  790. {Symbol &s=*Symbols("float" ); s.type=typedef_type; s.value="flt" ;}
  791. {Symbol &s=*Symbols("double" ); s.type=typedef_type; s.value="dbl" ;}
  792. #if X64
  793. {Symbol &s=*Symbols( "intptr" ); s.type=typedef_type; s.value= "long" ;}
  794. {Symbol &s=*Symbols("uintptr" ); s.type=typedef_type; s.value="ulong" ;}
  795. #else
  796. {Symbol &s=*Symbols( "intptr" ); s.type=typedef_type; s.value= "int" ;}
  797. {Symbol &s=*Symbols("uintptr" ); s.type=typedef_type; s.value="uint" ;}
  798. #endif
  799. {Symbol &s=*Symbols( "size_t"); s.type=typedef_type; s.value= "intptr";}
  800. {Symbol &s=*Symbols( "ssize_t"); s.type=typedef_type; s.value="uintptr";}
  801. {Symbol &s=*Symbols( "intptr_t"); s.type=typedef_type; s.value= "intptr";}
  802. {Symbol &s=*Symbols("uintptr_t"); s.type=typedef_type; s.value="uintptr";}
  803. {Symbol &s=*Symbols("wchar_t" ); s.type=typedef_type; s.value="char" ;}
  804. {Symbol &s=*Symbols("char16_t" ); s.type=typedef_type; s.value="char" ;}
  805. {Symbol &s=*Symbols("char32_t" ); s.type=typedef_type; s.value="uint" ;}
  806. {Symbol &s=*Symbols("__int8" ); s.type=typedef_type; s.value="sbyte" ;}
  807. {Symbol &s=*Symbols("__int16" ); s.type=typedef_type; s.value="short" ;}
  808. {Symbol &s=*Symbols("__int32" ); s.type=typedef_type; s.value="int" ;}
  809. {Symbol &s=*Symbols("__int64" ); s.type=typedef_type; s.value="long" ;}
  810. {Symbol &s=*Symbols("int8_t" ); s.type=typedef_type; s.value="sbyte" ;}
  811. {Symbol &s=*Symbols("uint8_t" ); s.type=typedef_type; s.value="byte" ;}
  812. {Symbol &s=*Symbols("int16_t" ); s.type=typedef_type; s.value="short" ;}
  813. {Symbol &s=*Symbols("uint16_t" ); s.type=typedef_type; s.value="ushort" ;}
  814. {Symbol &s=*Symbols("int32_t" ); s.type=typedef_type; s.value="int" ;}
  815. {Symbol &s=*Symbols("uint32_t" ); s.type=typedef_type; s.value="uint" ;}
  816. {Symbol &s=*Symbols("int64_t" ); s.type=typedef_type; s.value="long" ;}
  817. {Symbol &s=*Symbols("uint64_t" ); s.type=typedef_type; s.value="ulong" ;}
  818. {Symbol &s=*Symbols("signed" ); s.type=typedef_type; s.value="int" ;}
  819. {Symbol &s=*Symbols("unsigned" ); s.type=typedef_type; s.value="uint" ;}
  820. FREPA(PreprocKeywords)
  821. {
  822. SymbolDef &s=SymbolDefs.New().require(S+'#'+PreprocKeywords[i]);
  823. s->type=Symbol::PREPROC;
  824. FlagSet(s->modifiers, Symbol::MODIF_FOLLOW_BY_SPACE, *s!="#else" && *s!="#endif");
  825. }
  826. SystemMacros.New().set("__cplusplus");
  827. SystemMacros.New().set("_WIN32"); // for constant behavior across platforms, define _WIN32 everywhere
  828. SystemMacros.sort(CompareCS); // macros need to be sorted
  829. // setup gui
  830. if(T.parent) // only if we're adding it to parent, so we can create Code Editor in Esenthel Builder without using GUI at all
  831. {
  832. ts.reset();
  833. ts.align.set(1, -1);
  834. ts.shade =255;
  835. ts.spacing=SPACING_CONST;
  836. ts_small=ts;
  837. skinChanged();
  838. Node<MenuElm> menu_elms;
  839. setMenu(menu_elms);
  840. *parent+=menu.create(menu_elms).disabled(true);
  841. *parent+=b_close.create().func(MenuClose).hide().desc("Close current file"); b_close.image="Gui/close.img"; b_close.skin=&EmptyGuiSkin;
  842. Node<MenuElm> view_what_elms;
  843. view_what_elms.New().create("Element Names" , ViewElmNames ).flag(MENU_TOGGLABLE ).setOn(view_elm_names ).desc("Display project element names on top of their ID in the codes\nKeyboard Shortcut: Alt+E");
  844. view_what_elms++;
  845. view_what_elms.New().create("Comments" , ViewComments ).flag(MENU_TOGGLABLE ).setOn(view_comments ).desc("Show Comments");
  846. view_what_elms.New().create("Functions" , ViewFuncs ).flag(MENU_TOGGLABLE|MENU_HIDDEN).setOn(view_funcs ).desc("Show Functions");
  847. view_what_elms.New().create("Function Bodies", ViewFuncBodies ).flag(MENU_TOGGLABLE ).setOn(view_func_bodies ).desc("Show Function Bodies\nKeyboard Shortcut: Alt+B");
  848. view_what_elms.New().create("Private Members", ViewPrivateMembers).flag(MENU_TOGGLABLE ).setOn(view_private_members).desc("Show Class Private Members");
  849. *parent+=view_mode.create("View Mode").func(RefreshSourceLines, T).focusable(false).desc("Keyboard Shortcut: Alt+V");
  850. *parent+=view_what.create().setData(view_what_elms); view_what.menu_align=-1; view_what.flag|=COMBOBOX_CONST_TEXT;
  851. view_mode.mode=b_find.mode=BUTTON_TOGGLE;
  852. goto_line_window .create(T);
  853. options .create(T);
  854. android_certificate.create(T);
  855. {
  856. Gui+=build_progress.create();
  857. Gui+=build_region.create(); build_region.kb_lit=false;
  858. ListColumn lc[]=
  859. {
  860. ListColumn(MEMBER(BuildResult, text), LCW_MAX_DATA_PARENT, "Output"),
  861. };
  862. build_region+=build_list .create(lc, Elms(lc)).skin(&cjk_skin); build_list.column(0).disabled(true); build_list.cur_mode=LCM_MOUSE; build_list.setElmTextColor(MEMBER(BuildResult, color));
  863. Gui +=build_close .create().func(BuildClose, T); build_close.image="Gui/close.img"; build_close.skin=&EmptyGuiSkin;
  864. Gui +=build_export.create("Export").func(OutputExport, T);
  865. Gui +=build_copy .create("Copy" ).func(OutputCopy , T);
  866. Gui +=build_io .create("txt", S, SystemPath(SP_DESKTOP), OutputExport, OutputExport, T); build_io.textline.set("Output.txt");
  867. }
  868. {
  869. Gui+=devlog_region.create(); devlog_region.kb_lit=false;
  870. ListColumn lc[]=
  871. {
  872. ListColumn(MEMBER(DeviceLog, time ), 0.20f, "Time" ),
  873. ListColumn(MEMBER(DeviceLog, app ), 0.25f, "Application"),
  874. ListColumn(MEMBER(DeviceLog, message), LCW_MAX_DATA_PARENT, "Message"),
  875. };
  876. lc[0].sort=&devlog_time_sort; devlog_time_sort.setDataToTextFunc(DeviceLogOrder); // when sorting by time, then actually sort by order in the container
  877. devlog_region+=devlog_list .create(lc, Elms(lc)); devlog_list.cur_mode=LCM_MOUSE; devlog_list.setElmTextColor(MEMBER(DeviceLog, color));
  878. Gui +=devlog_close .create( ).func(DevlogClose , T); devlog_close.image="Gui/close.img"; devlog_close.skin=&EmptyGuiSkin;
  879. Gui +=devlog_filter.create("App Only").func(DevlogFilter2, T).desc("Display messages only from your application"); devlog_filter.mode=BUTTON_TOGGLE;
  880. Gui +=devlog_export.create("Export" ).func(DevlogExport , T);
  881. Gui +=devlog_clear .create("Clear" ).func(DevlogClear , T);
  882. Gui +=devlog_io .create("txt", S, SystemPath(SP_DESKTOP), DevlogExport, DevlogExport, T); devlog_io.textline.set("Android Device Log.txt");
  883. }
  884. find .create();
  885. replace.create();
  886. save_changes.create();
  887. visibleOutput(false);
  888. visibleOpenedFiles(false);
  889. visibleAndroidDevLog(false);
  890. resize();
  891. }
  892. if(!loadSymbols(CodeEditorDat, false)){}
  893. }
  894. void CodeEditor::genSymbols(C Str &ee_editor_bin)
  895. {
  896. ee_h_path=Str(ee_editor_bin).tailSlash(true)+"EsenthelEngine";
  897. FList(ee_h_path, AddEEHeader, T); // add all headers from folder to 'items'
  898. EEUsings.clear();
  899. EEMacros=SystemMacros;
  900. parseHeader(ee_h_path+"\\EsenthelEngine.h", EEMacros, EEUsings, true);
  901. // TODO: remove this after adding support for detection of "using namespace .." in sources
  902. EEUsings.New().find("EE");
  903. replacePath(ee_h_path, EE_PATH);
  904. SortItems(items);
  905. // remove macros
  906. CChar8 *remove_macros[]=
  907. {
  908. "super" , // use keyword instead of macro
  909. "null" , // use keyword instead of macro
  910. "null_t" , // use keyword instead of macro
  911. "NULL" , // use 'null' keyword
  912. "STRUCT" , // use "class A : B"
  913. "STRUCT_PRIVATE", // use "class A : private B"
  914. };
  915. #if 1
  916. REPAD(d, remove_macros)REPA(EEMacros)if(Equal(EEMacros[i].name, remove_macros[d], true))EEMacros.remove(i, true);
  917. #else
  918. REPAD(d, disable_macros)REPA(EEMacros)if(Equal(EEMacros[i].name, disable_macros[d], true))EEMacros[i].use_for_suggestions=false;
  919. #endif
  920. // disable EE basic data types suggestions
  921. SymbolPtr s;
  922. if(s.find("Bool" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  923. if(s.find( "Char8" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  924. if(s.find("CChar8" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  925. if(s.find( "Char" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  926. if(s.find("CChar" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  927. if(s.find("I8" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  928. if(s.find("U8" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  929. if(s.find("I16" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  930. if(s.find("U16" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  931. if(s.find("I32" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  932. if(s.find("U32" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  933. if(s.find("I64" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  934. if(s.find("U64" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  935. if(s.find("SByte" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  936. if(s.find("Byte" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  937. if(s.find("Short" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  938. if(s.find("UShort" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  939. if(s.find("Int" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  940. if(s.find("UInt" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  941. if(s.find("Long" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  942. if(s.find("ULong" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  943. if(s.find( "IntPtr")){FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS); s->value= "intptr";} // replace typedef with "intptr" because that one is changed for 32/64 compilation
  944. if(s.find("UIntPtr")){FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS); s->value="uintptr";} // replace typedef with "uintptr" because that one is changed for 32/64 compilation
  945. if(s.find("Flt" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  946. if(s.find("Dbl" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  947. if(s.find( "Ptr" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  948. if(s.find("CPtr" )) FlagEnable(s->modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);
  949. // disable suggestions for all symbols starting with a '_', because they're meant as hidden/private, but not all can be hidden in EE_PRIVATE (such as _Sort, _GameAnalytics, etc.)
  950. Symbols. lock(); REPA(Symbols){Symbol &symbol=Symbols.lockedData(i); if(symbol[0]=='_')FlagEnable(symbol.modifiers, Symbol::MODIF_SKIP_SUGGESTIONS);}
  951. Symbols.unlock();
  952. saveSymbols(Str(ee_editor_bin).tailSlash(true)+"Code Editor.dat");
  953. //createFuncList();
  954. }
  955. /******************************************************************************/
  956. void CodeEditor::init()
  957. {
  958. if(!symbols_loaded)
  959. {
  960. symbols_loaded=true;
  961. // setup defaults
  962. EEMacros=SystemMacros;
  963. // load
  964. #if LOAD_SYMBOLS
  965. if(!loadSymbols(CodeEditorDat))Exit("Error loading \"Code Editor.dat\".");
  966. #endif
  967. // setup project basing on libs
  968. ProjectMacros=LibMacros=EEMacros;
  969. ProjectUsings=LibUsings=EEUsings;
  970. // rebuild symbols of all sources that were loaded before the init
  971. rebuildSymbols(true);
  972. }
  973. }
  974. /******************************************************************************/
  975. Flt CodeEditor:: lineNumberSize()C {return options.line_numbers() ? ts.lineHeight()*2.3f : 0;}
  976. Flt CodeEditor::fontSpaceOffset()C {return (1-CE.ts.space.y)*CE.ts.size.y*0.5f;}
  977. Rect CodeEditor::sourceRect ()
  978. {
  979. Rect r(-D.w(), build_region.visible() ? build_region.rect().max.y : -D.h(), D.w(), D.h());
  980. if(menu.visibleFull())if(menu_on_top)MIN(r.max.y, menu.rect().min.y);else MAX(r.min.y, menu.rect().max.y); // check 'visibleFull' in case 'menu' is attached to a Tabs::Tab
  981. return r&cei().sourceRect();
  982. }
  983. Source* CodeEditor::findSource(C SourceLoc &loc) {if(loc.is())REPA(sources)if(sources[i].loc==loc)return &sources[i]; return null;}
  984. Source* CodeEditor:: getSource(C SourceLoc &loc, ERROR_TYPE *error)
  985. {
  986. Source *s=findSource(loc);
  987. if( !s && loc.is())
  988. {
  989. s=&sources.New();
  990. ERROR_TYPE e=s->load(loc); if(error)*error=e;
  991. if(e!=EE_ERR_NONE){sources.removeData(s, true); s=null;}
  992. }
  993. return s;
  994. }
  995. Int CodeEditor::curI() {return sources.validIndex(_cur);}
  996. Source* CodeEditor::cur () {return _cur ;}
  997. void CodeEditor::nextFile() {Source *src=null; Int offset=curI()+1; FREPA(sources){Source &s=sources[Mod(offset+i, sources.elms())]; if(s.opened){src=&s; break;}} cur(src);} // activate next opened source
  998. void CodeEditor::prevFile() {Source *src=null; Int offset=curI()-1; FREPA(sources){Source &s=sources[Mod(offset-i, sources.elms())]; if(s.opened){src=&s; break;}} cur(src);} // activate prev opened source
  999. Str CodeEditor::title()
  1000. {
  1001. if(cur())
  1002. {
  1003. Str path=cur()->loc.asText();
  1004. if( path.is())return S+'"'+path+(cur()->modified() ? '*' : '\0')+'"'+(cur()->Const ? " (Read Only)" : null);
  1005. }
  1006. return S;
  1007. }
  1008. Str CodeEditor::adbPath()C
  1009. {
  1010. if(android_sdk.is())
  1011. {
  1012. CChar8 *name=PLATFORM("adb.exe", "adb");
  1013. Str sdk=Str(android_sdk).tailSlash(true);
  1014. Str p=sdk+"platform-tools/"+name; if(FExistSystem(p))return p;
  1015. }
  1016. return S;
  1017. }
  1018. Str CodeEditor::zipalignPath()C
  1019. {
  1020. if(android_sdk.is())
  1021. {
  1022. CChar8 *name=PLATFORM("zipalign.exe", "zipalign");
  1023. Str sdk=Str(android_sdk).tailSlash(true);
  1024. Str p=sdk+"tools/"+name; if(FExistSystem(p))return p;
  1025. for(FileFind ff(sdk+"build-tools"); ff(); )p=ff.pathName()+'/'+name; if(FExistSystem(p))return p;
  1026. }
  1027. return S;
  1028. }
  1029. Str CodeEditor::ndkBuildPath()C
  1030. {
  1031. if(android_ndk.is())
  1032. {
  1033. CChar8 *name=PLATFORM("ndk-build.cmd", "ndk-build");
  1034. Str ndk=Str(android_ndk).tailSlash(true);
  1035. Str p=ndk+name; if(FExistSystem(p))return p;
  1036. }
  1037. return S;
  1038. }
  1039. /******************************************************************************/
  1040. static Bool EmbedAppResource(C Str &dest, File &src, UInt type) // used only for Linux apps
  1041. {
  1042. const UInt CC4_CHNK=CC4('C', 'H', 'N', 'K');
  1043. File f; if(f.appendTry(dest))
  1044. {
  1045. Long pos=f.pos();
  1046. f.putUInt(CC4_CHNK);
  1047. f.putUInt(4+src.left()); // type + src
  1048. f.putUInt(type); // type
  1049. if(src.copy(f)) // src
  1050. {
  1051. UInt skip=f.pos()-pos+4*2; // we're writing 2 UInt's:
  1052. f.putUInt(skip );
  1053. f.putUInt(CC4_CHNK);
  1054. return f.flushOK();
  1055. }
  1056. }
  1057. return false;
  1058. }
  1059. static Bool EmbedAppResource(C Str &dest, C Str &src, UInt type)
  1060. {
  1061. File f; if(f.readStdTry(src))return EmbedAppResource(dest, f, type);
  1062. return false;
  1063. }
  1064. void CodeEditor::BuildResult::setWarning() {mode=1; setColor();}
  1065. void CodeEditor::BuildResult::setError () {mode=2; setColor();}
  1066. void CodeEditor::BuildResult::setColor ()
  1067. {
  1068. switch(mode)
  1069. {
  1070. case 1: color.set(128, 128, 0); break;
  1071. case 2: color=RED; break;
  1072. default: if(GuiSkin *skin=Gui.skin())if(TextStyle *ts=skin->text.text_style()){color=ts->color; break;} color=BLACK; break;
  1073. }
  1074. }
  1075. void CodeEditor::DeviceLog::setWarning() {mode=WARNING; setColor();}
  1076. void CodeEditor::DeviceLog::setError () {mode=ERROR ; setColor();}
  1077. void CodeEditor::DeviceLog::setApp () {mode=APP ; setColor();}
  1078. void CodeEditor::DeviceLog::setColor ()
  1079. {
  1080. switch(mode)
  1081. {
  1082. case WARNING: color.set(128, 128, 0); break;
  1083. case ERROR : color=RED; break;
  1084. case APP : color.set(0, 128, 0); break;
  1085. default : if(GuiSkin *skin=Gui.skin())if(TextStyle *ts=skin->text.text_style()){color=ts->color; break;} color=BLACK; break;
  1086. }
  1087. }
  1088. static Str FindPath(C Str &registry, C Str &sub_path)
  1089. {
  1090. Str path=GetRegStr(RKG_LOCAL_MACHINE, registry); if(path.is())
  1091. {
  1092. path.tailSlash(true)+=sub_path;
  1093. if(FExistSystem(path))return path;
  1094. }
  1095. return S;
  1096. }
  1097. void CodeEditor::update(Bool active)
  1098. {
  1099. if(active)
  1100. {
  1101. if(Gui.kb()==&build_list)if(cur())cur()->activate();
  1102. if(Ms.bp(2) && build_region .contains(Gui.ms()))visibleOutput (false);
  1103. if(Ms.bp(2) && devlog_region.contains(Gui.ms()))visibleAndroidDevLog(false);
  1104. if(cur())cur()->suggestionsSetRect();
  1105. // highlight element containing token under mouse cursor
  1106. SourceLoc elm_highlight;
  1107. if(cur() && cur()->hasMsFocus() && CE.view_mode())
  1108. {
  1109. VecI2 view=Trunc(cur()->posCur(Ms.pos())), real;
  1110. if(cur()->viewToReal(view, real))
  1111. {
  1112. SymbolPtr symbol;
  1113. Macro *macro=null;
  1114. UID id;
  1115. if(cur()->getSymbolMacroID(real, symbol, macro, id))
  1116. {
  1117. if(symbol && symbol->source)elm_highlight=symbol->source->loc;else
  1118. if(macro && macro ->source)elm_highlight=macro ->source->loc;else
  1119. if(id.valid() )elm_highlight=id;
  1120. }
  1121. }
  1122. }
  1123. cei().elmHighlight(elm_highlight.id, elm_highlight.file_name);
  1124. // auto-hide menu
  1125. if(options.auto_hide_menu())setMenuBarVisibility();
  1126. #if 0 // display 'view_what.menu' when hovering over the 'view_mode' button
  1127. if(!view_what.button()())
  1128. {
  1129. Bool make_vis=(view_mode.contains(Gui.ms()) || view_what.menu.contains(Gui.ms()));
  1130. if(view_what.menu.visible()!=make_vis)
  1131. {
  1132. if(make_vis)view_what.menu.posAround(view_what.screenRect(), view_what.menu_align);
  1133. view_what.menu.visibleToggleActivate();
  1134. }
  1135. }
  1136. #endif
  1137. }
  1138. build_progress.visible(build_process.created());
  1139. if(build_process.created())
  1140. {
  1141. build_progress.set(build_steps ? build_step+1 : build_phase+1, build_steps ? build_steps+1 : build_phases+1);
  1142. Bool active =build_process.active(), // get information about active before reading output
  1143. refresh=false;
  1144. if(build_log.is()) // read from file
  1145. {
  1146. if((build_refresh-=Time.rd())<=0 || !active)
  1147. {
  1148. build_refresh=0.25f;
  1149. refresh=true;
  1150. }
  1151. }else // read from process
  1152. {
  1153. Str output=build_process.get();
  1154. if( output.is())
  1155. {
  1156. FREPA(output)
  1157. {
  1158. Char c=output[i];
  1159. if(c=='\t')build_output+=" ";else
  1160. if(c==L'‘')build_output+='\'' ;else // occurs on Linux
  1161. if(c==L'’')build_output+='\'' ;else // occurs on Linux
  1162. build_output+=c;
  1163. }
  1164. refresh=true;
  1165. }
  1166. }
  1167. Bool at_end=build_region.slidebar[1].wantedAtEnd(0.02f);
  1168. if(refresh)
  1169. {
  1170. Memc<Str> lines;
  1171. if(build_log.is()) // read from file
  1172. {
  1173. FileText f; if(f.read(build_log))for(; !f.end(); )f.fullLine(lines.New());
  1174. }else // read from process
  1175. {
  1176. lines=Split(build_output, '\n');
  1177. }
  1178. buildClear();
  1179. if(build_exe_type==EXE_EXE || build_exe_type==EXE_DLL || build_exe_type==EXE_LIB || build_exe_type==EXE_NEW || build_exe_type==EXE_MAC || build_exe_type==EXE_IOS || build_exe_type==EXE_LINUX || build_exe_type==EXE_WEB)build_step=0; // we're going to count compilation progress for these platforms
  1180. FREPA(lines)
  1181. {
  1182. C Str &line=lines[i];
  1183. if(SkipWhiteChars(line).is())
  1184. if(build_exe_type!=EXE_APK || // hide some Android compiler/linker warnings
  1185. !Contains(line, "uses 2-byte wchar_t yet the output is to use 4-byte wchar_t; use of wchar_t values across objects may fail")
  1186. && !Contains(line, "uses 4-byte wchar_t yet the output is to use 2-byte wchar_t; use of wchar_t values across objects may fail")
  1187. )
  1188. if(!Contains(line, "manifest authoring warning 81010002:"))
  1189. {
  1190. BuildResult &br=buildNew().set(line);
  1191. if(Contains(line, "warning:", false, true)
  1192. || Contains(line, ": warning" , false, true))br.setWarning();else
  1193. if(Contains(line, "error:" , false, true)
  1194. || Contains(line, ": error " , false, true))br.setError ();
  1195. // count sources compiled
  1196. if(build_exe_type==EXE_EXE || build_exe_type==EXE_DLL || build_exe_type==EXE_LIB || build_exe_type==EXE_NEW || build_exe_type==EXE_WEB)
  1197. {
  1198. if(build_msbuild)
  1199. {
  1200. if(line[0]==' ' && line[1]==' ')
  1201. {
  1202. if(Ends(line, ".cpp"))
  1203. {
  1204. CChar *l=_SkipWhiteChars(line()+2);
  1205. if(CleanFileName(l)==l)build_step++;
  1206. }else
  1207. if(line==" Generating Code...")build_step++;
  1208. }
  1209. }else
  1210. FREPA(line)
  1211. {
  1212. if(CharFlag(line[i])&CHARF_DIG){}else
  1213. if(line[i]=='>')
  1214. {
  1215. Str l=SkipWhiteChars(line()+i+1);
  1216. if(Ends(l, ".cpp") && CleanFileName(l)==l || Equal(l, "linking..."))build_step++;
  1217. }else break;
  1218. }
  1219. }else
  1220. if(build_exe_type==EXE_MAC || build_exe_type==EXE_IOS)
  1221. {
  1222. if(Starts(line, "CompileC", true, true)
  1223. || Starts(line, "Ld" , true, true))build_step++;
  1224. if(Starts(line, "Undefined symbols", true, true)
  1225. || Starts(line, "ld: framework not found" ))br.setError();
  1226. }else
  1227. if(build_exe_type==EXE_LINUX)
  1228. {
  1229. if(Starts(line, "g++" , true, true)
  1230. || Starts(line, "clang++" , true, true))build_step++;
  1231. if(Starts(line, "/usr/bin/ld: cannot find", true, true))br.setError();
  1232. }
  1233. }
  1234. }
  1235. buildUpdate(false);
  1236. if(at_end)build_region.scrollEndY(); // auto-scroll to the end
  1237. }
  1238. if(!active) // process finished building
  1239. {
  1240. Int exit_code=build_process.exitCode();
  1241. build_process.del();
  1242. Bool was_log;
  1243. if(was_log=build_log.is()){FDelFile(build_log); build_log.clear();}
  1244. if(build_exe_type==EXE_EXE || build_exe_type==EXE_DLL || build_exe_type==EXE_LIB || build_exe_type==EXE_NEW || build_exe_type==EXE_WEB)
  1245. {
  1246. Bool ok=false;
  1247. if(build_phase==0)
  1248. {
  1249. if(exit_code>=0)ok=(exit_code==0);else // exit code known
  1250. if(build_data.elms()) // detect success
  1251. {
  1252. C Str &last=build_data.last().text;
  1253. if(Starts(last, "==="))
  1254. {
  1255. // only on success
  1256. ok=(((Contains(last, "1 succeeded" ) || Contains(last, "1 up-to-date" )) && Contains(last, "0 failed" )) // English (========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========)
  1257. || ((Contains(last, "1 erfolgreich") || Contains(last, "1 aktuell" )) && Contains(last, "Fehler bei 0" )) // German (========== Build: 1 erfolgreich, Fehler bei 0, 0 aktuell, 0 übersprungen ==========)
  1258. || ((Contains(last, u"1 a réussi" ) || Contains(last, u"1 mis à jour" )) && Contains(last, u"0 a échoué" )) // French (========== Génération : 1 a réussi, 0 a échoué, 0 mis à jour, 0 a été ignoré ==========)
  1259. || ((Contains(last, "1 completate" ) || Contains(last, "1 aggiornate" )) && Contains(last, "0 non riuscite")) // Italian (========== Compilazione: 1 completate, 0 non riuscite, 0 aggiornate, 0 ignorate ==========)
  1260. || ((Contains(last, u"успешно: 1" ) || Contains(last, u"без изменений: 1")) && Contains(last, u"с ошибками: 0" ))); // Russian (========== Построение: успешно: 1, с ошибками: 0, без изменений: 0, пропущено: 0 ==========)
  1261. }
  1262. }
  1263. if(1 && ok) // store hash, !! have to do this before Code Signing, because we modify the EXE file, otherwise it would make the signature invalid !!
  1264. if(!build_debug) // skip for DEBUG because it interferes with incremental linking
  1265. if(build_exe_type==EXE_EXE || build_exe_type==EXE_DLL)
  1266. {
  1267. File f; if(f.readStdTry(build_exe))
  1268. {
  1269. Memc<ExeSection> sections; if(ParseExe(f, sections))
  1270. {
  1271. xxHash64 file_hash;
  1272. C ExeSection *section_hash_ptr=null;
  1273. FREPA(sections) // process in order
  1274. {
  1275. C ExeSection &section=sections[i]; switch(section.type)
  1276. {
  1277. case ExeSection::VARIABLE: break; // don't calc hash because this section data can be outside of file range
  1278. case ExeSection::HASH : section_hash_ptr=&section; break; // remember HASH section for use later
  1279. default:
  1280. {
  1281. if(!f.pos(section.offset))goto hash_error;
  1282. ULong section_hash=f.xxHash64(section.size); if(!f.ok())goto hash_error; // get hash of this section
  1283. file_hash.update(&section_hash, SIZE(section_hash)); // update file hash based on section hash, use this method so in the app we can just once calculate hash per section just like here, and combine section hashes for final hash
  1284. }break;
  1285. }
  1286. }
  1287. if(section_hash_ptr && (build_debug ? section_hash_ptr->size>=SIZE(ULong) : section_hash_ptr->size==SIZE(ULong))) // when building in DEBUG mode, some extra data may be allocated
  1288. {
  1289. ULong hash=file_hash();
  1290. if(Cipher *cipher=CE.cei().appEmbedCipher())cipher->encrypt(&hash, &hash, SIZE(hash), 0); // encrypt with project cipher
  1291. if(!f.pos(section_hash_ptr->offset))goto hash_error;
  1292. if( f.getULong()==hash)goto hash_ok; // file already has correct hash, check this in case we are building for 2nd time and file was already adjusted, perhaps that EXE is already running so we can't modify it
  1293. if( f.appendTry(build_exe) && f.pos(section_hash_ptr->offset)) // modify hash
  1294. {
  1295. f.putULong(hash);
  1296. if(f.flushOK())goto hash_ok;
  1297. }
  1298. }
  1299. }
  1300. }
  1301. hash_error: BuildError("Error: Can't set EXE hash", at_end); //ok=false; ignore clearing 'ok' to allow proceeding in case hash is not needed by the user
  1302. hash_ok :;
  1303. }
  1304. if(ok)
  1305. {
  1306. build_phase++;
  1307. if(build_windows_code_sign) // !! have to do this after storing Hash !! CodeSigning will not change any ExeSection offset, size or data
  1308. {
  1309. Str signtool=FindPath("Software/Microsoft/Windows App Certification Kit/InstallLocation" , "signtool.exe");
  1310. if(!signtool.is())signtool=FindPath("Software/Microsoft/Microsoft SDKs/Windows/v10.0/InstallationFolder", "App Certification Kit\\signtool.exe");
  1311. if(!signtool.is())signtool=FindPath("Software/Microsoft/Windows Kits/Installed Roots/KitsRoot10" , "App Certification Kit\\signtool.exe");
  1312. if(!build_process.create(signtool, S+"sign /a \""+build_exe+'"'))
  1313. {
  1314. BuildError("Error: Can't do Windows Code Sign - SignTool (signtool.exe) was not found. Please download it from the internet", at_end);
  1315. }else // copy current output so it will be displayed for next phase as well
  1316. {
  1317. if(was_log)FREPA(build_data)build_output.line()+=build_data[i].text;
  1318. build_output.line();
  1319. }
  1320. }
  1321. }
  1322. }else
  1323. if(build_phase==(build_windows_code_sign ? 1 : -2))
  1324. {
  1325. ok=(exit_code==0);
  1326. if(ok)build_phase++;
  1327. }
  1328. if(ok && build_phase==(build_windows_code_sign ? 2 : 1))switch(build_mode)
  1329. {
  1330. case BUILD_PLAY:
  1331. {
  1332. switch(build_exe_type)
  1333. {
  1334. case EXE_EXE: Run(build_exe); break;
  1335. case EXE_WEB: goto publish; // when playing for WEB we will create PAK's after compilation, so call publish success to do so
  1336. }
  1337. }break;
  1338. //case BUILD_DEBUG : if(build_exe_type==EXE_EXE)VSRun(build_project_file); break; // no need to call this because building was done by launching VS and it will automatically run the app
  1339. case BUILD_PUBLISH: publish: cei().publishSuccess(build_exe, build_exe_type, build_mode, build_project_id); break;
  1340. }
  1341. }else
  1342. if(build_exe_type==EXE_LINUX)
  1343. {
  1344. Bool ok=(exit_code==0); // exit code is available on Linux
  1345. if( ok)
  1346. {
  1347. // on Linux we had to use temp exe name because 'make' fails for some characters
  1348. Str new_exe=GetPath(build_exe).tailSlash(true)+build_project_name; // set new name
  1349. if(!FRename(build_exe, new_exe))Gui.msgBox(S, S+"Can't rename file from: "+build_exe+"\nto: "+new_exe);else
  1350. {
  1351. build_exe=new_exe;
  1352. // embed app resources
  1353. FREPA(build_embed)
  1354. {
  1355. BuildEmbed &be=build_embed[i];
  1356. if(!EmbedAppResource(build_exe, be.path, be.type)){Gui.msgBox(S, "Can't embed app resource"); ok=false; break;}
  1357. }
  1358. build_embed.clear();
  1359. if(ok)switch(build_mode)
  1360. {
  1361. case BUILD_PLAY :
  1362. case BUILD_DEBUG : Run(build_exe); break;
  1363. case BUILD_PUBLISH: cei().publishSuccess(build_exe, build_exe_type, build_mode, build_project_id); break;
  1364. }
  1365. }
  1366. }
  1367. }else
  1368. if(build_exe_type==EXE_MAC)
  1369. {
  1370. Bool ok=false;
  1371. //if(exit_code>=0)ok=(exit_code==0);else // exit code known
  1372. if(build_data.elms())ok=(build_data.last().text=="** BUILD SUCCEEDED **"); // detect success
  1373. if(ok)switch(build_mode)
  1374. {
  1375. case BUILD_PLAY :
  1376. case BUILD_DEBUG : Run(build_exe); break;
  1377. case BUILD_PUBLISH: cei().publishSuccess(build_exe, build_exe_type, build_mode, build_project_id); break;
  1378. }
  1379. }else
  1380. if(build_exe_type==EXE_APK)
  1381. {
  1382. if(build_phase==0) // link with ant
  1383. {
  1384. // can't use 'exit_code' because it's always zero, #AndroidArchitecture
  1385. //if(!FExistSystem(build_path+"Android/libs/armeabi/libProject.so" ))BuildError("Failed to build armeabi shared library" , at_end);else
  1386. if(!FExistSystem(build_path+"Android/libs/armeabi-v7a/libProject.so"))BuildError("Failed to build armeabi-v7a shared library", at_end);else
  1387. if(!FExistSystem(build_path+"Android/libs/arm64-v8a/libProject.so" ))BuildError("Failed to build arm64-v8a shared library" , at_end);else
  1388. //if(!FExistSystem(build_path+"Android/libs/x86/libProject.so" ))BuildError("Failed to build x86 shared library" , at_end);else
  1389. {
  1390. if(build_exe.is()){build_exe+=(build_debug ? "-debug.apk" : "-release-unsigned.apk"); FDelFile(build_exe);} // delete it so we can know that the build was ok if it reappears
  1391. build_phase++;
  1392. build_process.create(GetPath(App.exe())+PLATFORM("/Bin/Android/Ant/bin/ant.bat", "/Bin/Android/Ant/bin/ant"), S+(build_debug ? "debug" : "release")+" -f \""+build_path+"Android\\build.xml\""+(build_log.is() ? S+" > \""+build_log+"\"" : S)); // Mac script "Android/Ant/bin/ant" must have changed "JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home" to "JAVA_HOME=$(/usr/libexec/java_home)" !! (without this building Android apps won't work on Mac)
  1393. }
  1394. }else
  1395. if(build_phase==(build_debug ? -2 : 1)) // sign with jarsigner
  1396. {
  1397. Bool ok=FExistSystem(build_exe); // can't use 'exit_code' because it's always zero
  1398. if( ok) // build succeeded
  1399. {
  1400. build_phase++;
  1401. build_process.create(PLATFORM(jdk_path.tailSlash(true)+"bin/jarsigner.exe", "jarsigner"), S+"-verbose -sigalg MD5withRSA -digestalg SHA1 -storepass \""+cert_pass+"\" -keypass \""+cert_pass+"\" -keystore \""+cert_file+"\" \""+build_exe+"\" \"key\"");
  1402. }
  1403. }else
  1404. if(build_phase==(build_debug ? -2 : 2)) // align with zipalign
  1405. {
  1406. if(exit_code==0) // sign succeeded
  1407. {
  1408. // force stop previous installation
  1409. Str src=build_exe, dest=SkipEnd(src, "-release-unsigned.apk")+".apk"; FDelFile(dest); build_exe=dest; // delete it so we can know that the align was ok if it reappears
  1410. build_phase++;
  1411. build_process.create(zipalignPath(), S+"-v 4 \""+src+"\" \""+dest+"\"");
  1412. }else
  1413. {
  1414. FDelFile(build_exe);
  1415. }
  1416. }else
  1417. if(build_phase==(build_debug ? 1 : 3)) // force stop
  1418. {
  1419. if(build_debug) // rename "*-debug.apk" ?
  1420. {
  1421. }else // remove "*-release-unsigned.apk"
  1422. {
  1423. FDelFile(SkipEnd(build_exe, ".apk")+"-release-unsigned.apk");
  1424. }
  1425. Bool ok=FExistSystem(build_exe); // can't use 'exit_code' because it's always zero
  1426. if( ok)switch(build_mode) // build succeeded
  1427. {
  1428. case BUILD_PLAY :
  1429. case BUILD_DEBUG:
  1430. {
  1431. // force stop previous installation
  1432. build_phase++;
  1433. build_process.create(adbPath(), S+"shell am force-stop \""+build_package+"\"");
  1434. }break;
  1435. case BUILD_PUBLISH: cei().publishSuccess(build_exe, build_exe_type, build_mode, build_project_id); break;
  1436. }
  1437. }else
  1438. if(build_phase==(build_debug ? 2 : 4)) // install on the device
  1439. {
  1440. build_phase++;
  1441. install:
  1442. build_process.create(adbPath(), S+"-d install -r \""+build_exe+"\""); // -r does reinstall if already exists
  1443. }else
  1444. if(build_phase==(build_debug ? 3 : 5)) // start on the device
  1445. {
  1446. Bool ok=false; // can't use 'exit_code' because it's always zero
  1447. FREP(Min(build_data.elms(), 2)) // check 2 last messages
  1448. {
  1449. C Str &s=build_data[build_data.elms()-1-i].text;
  1450. if(Contains(s, "Success")){ok=true; break;}
  1451. }
  1452. if(!ok && build_data.elms() && build_data.last().text=="- waiting for device -")goto install; // if just connected to a device, then try again
  1453. if(ok)
  1454. {
  1455. // start on the device without -n parameter
  1456. // the command has optional -n parameter which it seems that forces resume of an application (and its last memory state) from the AndroidMain (start) without any closing/resetting
  1457. // without this parameter Android 2.3 has trouble to start the app (intent not detected)
  1458. // that's why in 1st attempt start is tried without the parameter, if it will fail, then it's started with the parameter
  1459. // in order to avoid app weird behaviour with the -n parameter, engine detects at startup (in AndroidMain) if Jni is null
  1460. // if yes then it means that app memory state is ok or it was shut down properly, if not then it calls Exit immediattely
  1461. // the "shell am start" command works that if the app exited immediattely then it tries to launch it again, so even in case of Exit the app will be restarted
  1462. // side note: when trying to solve the memory issue by clearing java values to null helped, however when trying to activate the opengl context it seemed to be ok (in 'androidOpen'), however when using it in the app loop, the open gl context seemed null
  1463. build_phase++;
  1464. build_process.create(adbPath(), S+"shell am start \""+build_package+"/.LoaderActivity\"");
  1465. }
  1466. }else
  1467. if(build_phase==(build_debug ? 4 : 6)) // activate logcat
  1468. {
  1469. visibleAndroidDevLog(true);
  1470. if(build_data.elms())
  1471. {
  1472. if(Contains(build_data.last().text, "Activity not started, unable to resolve Intent"))
  1473. {
  1474. // start on the device thout -n parameter
  1475. build_phase++;
  1476. build_process.create(adbPath(), S+"shell am start -n \""+build_package+"/.LoaderActivity\""); // start with -n this time
  1477. }
  1478. }
  1479. }
  1480. }
  1481. }
  1482. }
  1483. if(devlog_process.created())
  1484. {
  1485. Str log=devlog_process.get();
  1486. if( log.is())
  1487. {
  1488. devlog_text+=log;
  1489. Memc<Str> lines=Split(devlog_text, '\n');
  1490. if(lines.elms()>=2)
  1491. {
  1492. Bool at_end=devlog_region.slidebar[1].wantedAtEnd(0.02f);
  1493. FREP(lines.elms()-1)
  1494. {
  1495. Str &l=lines[i]; // "mm-dd hh:mm:ss.123 D/name( pid): msg
  1496. if(l[0]!='-')if(CChar *time=TextPos(l, ' ')) // skip date "mm-dd"
  1497. {
  1498. time++;
  1499. if(CChar *debug=TextPos(time, ' '))
  1500. {
  1501. debug++;
  1502. DeviceLog &dl=devlog_data.New();
  1503. Char t[9]; Set(t, time); dl.time=t;
  1504. if(CChar *app=TextPos(debug, '/'))
  1505. {
  1506. app++;
  1507. if(CChar *pid=TextPos(app, '('))
  1508. {
  1509. for(; app<pid; )dl.app+=*app++; for(;dl.app.last()==' ';)dl.app.removeLast();
  1510. if(CChar *msg=TextPos(pid, ':'))
  1511. {
  1512. msg++; if(*msg==' ')msg++;
  1513. dl.message=msg;
  1514. }
  1515. }
  1516. }
  1517. if(Equal(dl.app, "Esenthel") )dl.setApp ();else
  1518. if(*debug=='D' )dl.setWarning();else
  1519. if(*debug=='E' || *debug=='F')dl.setError ();
  1520. // filter out unwanted messages
  1521. if(Equal(dl.app, "AlarmManager")
  1522. || Equal(dl.app, "Lights") // on HTC control screen brightness
  1523. || Equal(dl.app, "Sensors") // gyroscope, accelerometer, etc
  1524. //|| Equal(dl.app, "Ethernet")
  1525. //|| Equal(dl.app, "WifiService")
  1526. || Equal(dl.app, "BatteryService")
  1527. || Equal(dl.app, "BATT_ALG")
  1528. || Equal(dl.app, "TabletStatusBar")
  1529. || Equal(dl.app, "CameraService")
  1530. || Equal(dl.app, "NvOmxCamera")
  1531. || Equal(dl.app, "NvOmxCameraBuffers")
  1532. || Equal(dl.app, "NvOmxCameraCallbacks")
  1533. || Equal(dl.app, "NvOmxCameraSettings")
  1534. || Equal(dl.app, "NvOmxCameraSettingsParser")
  1535. || Equal(dl.app, "PowerManagerService")
  1536. || Equal(dl.app, "DownloadManager")
  1537. || Equal(dl.app, "[WeatherService]")
  1538. || Equal(dl.app, "[WeatherService1]")
  1539. || Equal(dl.app, "[WeatherReceiver]")
  1540. || Equal(dl.app, "[WeatherSettingsAdapter]")
  1541. || Equal(dl.app, "Unity")
  1542. ||(Equal(dl.app, "DalvikVM") && (Starts(dl.message, "GC_EXPLICIT") || Starts(dl.message, "GC_CONCURRENT")))
  1543. ||(Equal(dl.app, "LocationManagerService") && Starts(dl.message, "getLastLocation: Request"))
  1544. )devlog_data.removeLast();
  1545. }
  1546. }
  1547. }
  1548. devlog_text=lines.last();
  1549. Int remove=Max(0, devlog_data.elms()-LOG_LINES), remove_vis=remove; // keep last LOG_LINES lines
  1550. if(devlog_filter()){remove_vis=0; FREP(remove)remove_vis+=(devlog_data[i].mode==DeviceLog::APP);}
  1551. devlog_data.removeNum(0, remove, true);
  1552. if(devlog_list.lit>=0)devlog_list.lit-=remove_vis;
  1553. if(devlog_list.cur>=0)devlog_list.cur-=remove_vis;
  1554. if(!at_end)devlog_region.scrollY(-remove_vis*devlog_list.elmHeight(), true); // keep current position, call before 'DevlogFilter' so it can use current position to detect 'lit/cur'
  1555. DevlogFilter(T);
  1556. if(at_end)devlog_region.scrollEndY(); // auto-scroll to the end
  1557. }
  1558. }
  1559. }
  1560. if(adb_server.created() && !adb_server.active()) // ADB server finished starting
  1561. {
  1562. adb_server.del();
  1563. if(!devlog_process.active() && adb_path.is())
  1564. {
  1565. devlog_data.New().message="Android Debug Bridge Started, Starting LogCat..";
  1566. devlog_list.setData(devlog_data);
  1567. devlog_process.create(adb_path, "logcat -v time");
  1568. }
  1569. }
  1570. }
  1571. /******************************************************************************/
  1572. void CodeEditor::draw()
  1573. {
  1574. D.clearCol(cur() ? Theme.colors[TOKEN_NONE] : GREY);
  1575. }
  1576. /******************************************************************************/
  1577. void CodeEditor::rebuild3rdPartyHeaders()
  1578. {
  1579. // reset headers (except EE headers)
  1580. REPA(sources)
  1581. {
  1582. Source &src=sources[i];
  1583. if(src.header && !src.ee_header)
  1584. {
  1585. src.header=false; // first clear 'header' before resetting symbols
  1586. src.resetSymbols();
  1587. }
  1588. src.parse_count=0;
  1589. }
  1590. // parse all 3rd party headers
  1591. LibUsings.clear();
  1592. LibMacros=SystemMacros;
  1593. Memc<Str> headers; // TODO: this should be set based on selected target platform
  1594. #if WINDOWS
  1595. headers=GetFiles(cei().appHeadersWindows());
  1596. #elif MAC
  1597. headers=GetFiles(cei().appHeadersMac());
  1598. #elif LINUX
  1599. headers=GetFiles(cei().appHeadersLinux());
  1600. #endif
  1601. FREPA(headers)parseHeader(headers[i], LibMacros, LibUsings, false);
  1602. // remove system macros incompatible with EE
  1603. REPA(LibMacros)if(LibMacros[i]=="min" || LibMacros[i]=="max")LibMacros.remove(i, true);
  1604. // add stuff from EE
  1605. REPA(EEUsings)LibUsings.include(EEUsings[i]); // include all usings defined by EE
  1606. REPA(EEMacros)LibMacros.exclude(EEMacros[i]); // remove all macros defined by EE (to avoid duplicates, and replace old ones with new ones)
  1607. REPA(EEMacros)LibMacros.add (EEMacros[i]); // add all macros defined by EE
  1608. LibMacros.sort(CompareCS); // macros need to be sorted
  1609. ProjectMacros=LibMacros;
  1610. ProjectUsings=LibUsings;
  1611. }
  1612. /******************************************************************************/
  1613. void CodeEditor::rebuildSymbols(Bool rebuild_3rd_party_headers)
  1614. {
  1615. REPAO(sources).resetSymbols ();
  1616. if(rebuild_3rd_party_headers)rebuild3rdPartyHeaders();
  1617. // setup custom macros
  1618. Macro *macro; Int index;
  1619. CChar8 *name="STEAM" ; if(ProjectMacros.binarySearch(name, index, CompareCS))macro=&ProjectMacros[index];else macro=&ProjectMacros.NewAt(index).set(name); macro->def=cei().appPublishSteamDll (); macro->parts.setNum(1)[0].set(TOKEN_NUMBER, -1, &BStr().setBorrowed(macro->def));
  1620. name="OPEN_VR"; if(ProjectMacros.binarySearch(name, index, CompareCS))macro=&ProjectMacros[index];else macro=&ProjectMacros.NewAt(index).set(name); macro->def=cei().appPublishOpenVRDll(); macro->parts.setNum(1)[0].set(TOKEN_NUMBER, -1, &BStr().setBorrowed(macro->def));
  1621. REPAO(sources).detectDefines ();
  1622. REPAO(sources).preprocess ();
  1623. REPAO(sources).detectDataTypes();
  1624. REPAO(sources).linkDataTypes ();
  1625. REPAO(sources).detectVarFuncs ();
  1626. }
  1627. /******************************************************************************/
  1628. void CodeEditor::validateActiveSources(Bool rebuild_3rd_party_headers) {cei().validateActiveSources();} // ignore 'rebuild_3rd_party_headers' for simplicity
  1629. /******************************************************************************/
  1630. static void CloseAll(Bool all_saved=true, Ptr user=null) {CE.closeAll();}
  1631. void CodeEditorInterface::del () {CE.del();}
  1632. void CodeEditorInterface::clear () {CE.closeAll(); CE.sources.removeData(CE.findSource(Str(AutoSource)), true); clearActiveSources(); activateApp(true);}
  1633. void CodeEditorInterface::create (GuiObj &parent, Bool menu_on_top) { CE.cei(T); CE.create(&parent, menu_on_top);}
  1634. void CodeEditorInterface::update (Bool active ) { CE.update(active);}
  1635. void CodeEditorInterface::draw ( ) { CE.draw ( );}
  1636. void CodeEditorInterface::resize ( ) { CE.resize( );}
  1637. void CodeEditorInterface::skinChanged( ) { CE.skinChanged ();}
  1638. Bool CodeEditorInterface::initialized( ) {return CE.symbols_loaded;}
  1639. Str CodeEditorInterface::title ( ) {return CE.title ( );}
  1640. Str CodeEditorInterface::appPath (C Str &app_name ) {Str build_path, build_project_name; return CE.getBuildPath(build_path, build_project_name, &app_name) ? build_path : S;}
  1641. Str CodeEditorInterface::androidProjectPakPath( ) {Str build_path, build_project_name; return CE.getBuildPath(build_path, build_project_name ) ? build_path+"Android/assets/Project.pak" : S;}
  1642. Str CodeEditorInterface:: iOSProjectPakPath( ) {Str build_path, build_project_name; return CE.getBuildPath(build_path, build_project_name ) ? build_path+"Assets/Project.pak" : S;}
  1643. Str CodeEditorInterface::windowsProjectPakPath( ) {Str build_path, build_project_name; return CE.getBuildPath(build_path, build_project_name ) ? build_path+"Project.pak" : S;} // if we would set "Assets/Project.pak" then the file would be included inside the EXE including the "Assets" too
  1644. void CodeEditorInterface::saveChanges( ) {CE.saveChanges();}
  1645. void CodeEditorInterface::saveChanges(Memc<Edit::SaveChanges::Elm> &elms ) {CE.saveChanges(elms);}
  1646. void CodeEditorInterface::saveChanges(Memc<Edit::SaveChanges::Elm> &elms, void (*after_save_close)(Bool all_saved, Ptr user), Ptr user) {CE.save_changes.set(elms, after_save_close, user);}
  1647. void CodeEditorInterface::sourceRename (C UID &id ) {SourceLoc loc=id; if(Source *source=CE.findSource(loc))source->loc=loc;}
  1648. Bool CodeEditorInterface::sourceCur (C Str &name) {CE.init(); return CE.load(name);} // 'init' in case we're loading source from data
  1649. Bool CodeEditorInterface::sourceCur (C UID &id ) { return CE.load(id );}
  1650. Bool CodeEditorInterface::sourceCurIs ( ) {return CE.cur()!=null;}
  1651. Str CodeEditorInterface::sourceCurName ( ) {return CE.cur() ? CE.cur()->loc.file_name : S ;}
  1652. UID CodeEditorInterface::sourceCurId ( ) {return CE.cur() ? CE.cur()->loc.id : UIDZero;}
  1653. Bool CodeEditorInterface::sourceCurModified( ) {return CE.cur() ? CE.cur()->modified() : false ;}
  1654. Bool CodeEditorInterface::sourceCurConst ( ) {return CE.cur() ? CE.cur()->Const : false ;}
  1655. void CodeEditorInterface::projectsBuildPath(C Str &path) {CE.projects_build_path=path;} // !! 'projects_build_path' may get deleted in 'cleanAll' !!
  1656. void CodeEditorInterface::menuEnabled (Bool on) {CE.menu.enabled(on);}
  1657. void CodeEditorInterface::hideAll ( ) {CE.hideAll();}
  1658. Bool CodeEditorInterface::visibleOptions ( ) {return CE.options.visible();}
  1659. void CodeEditorInterface::visibleOptions (Bool on) { CE.options.visibleActivate(on);}
  1660. Bool CodeEditorInterface::visibleOpenedFiles ( ) {return CE.visibleOpenedFiles ( );}
  1661. void CodeEditorInterface::visibleOpenedFiles (Bool on) { CE.visibleOpenedFiles (on);}
  1662. Bool CodeEditorInterface::visibleOutput ( ) {return CE.visibleOutput ( );}
  1663. void CodeEditorInterface::visibleOutput (Bool on) { CE.visibleOutput (on);}
  1664. Bool CodeEditorInterface::visibleAndroidDevLog( ) {return CE.visibleAndroidDevLog( );}
  1665. void CodeEditorInterface::visibleAndroidDevLog(Bool on) { CE.visibleAndroidDevLog(on);}
  1666. void CodeEditorInterface::paste(C MemPtr<UID> &elms, GuiObj *obj, C Vec2 &screen_pos)
  1667. {
  1668. if(Source *src=CE.cur())
  1669. if(!src->Const && src->contains(obj) && elms.elms())
  1670. {
  1671. Str text;
  1672. Vec2 c=src->posCur(screen_pos); MAX(c.x, 0); MAX(c.y, 0);
  1673. src->sel=src->sel_temp=-1;
  1674. src->cur.set(Round(c.x), Trunc(c.y)); if(CE.view_mode())src->viewToReal(src->cur, src->cur);
  1675. src->curClip();
  1676. FREPA(elms)
  1677. {
  1678. if(i)
  1679. {
  1680. if(Kb.ctrlCmd())REP(src->cur.x)text+=' ';else text+=", ";
  1681. }
  1682. text+=elms[i].asCString();
  1683. if(Kb.ctrlCmd())text+=",\n";
  1684. }
  1685. src->paste(&text);
  1686. }
  1687. }
  1688. void CodeEditorInterface::paste(C Str &text, GuiObj *obj, C Vec2 &screen_pos)
  1689. {
  1690. if(Source *src=CE.cur())
  1691. if(!src->Const && src->contains(obj) && text.is())
  1692. {
  1693. Vec2 c=src->posCur(screen_pos); MAX(c.x, 0); MAX(c.y, 0);
  1694. src->sel=src->sel_temp=-1;
  1695. src->cur.set(Round(c.x), Trunc(c.y)); if(CE.view_mode())src->viewToReal(src->cur, src->cur);
  1696. src->curClip();
  1697. src->paste(&text);
  1698. }
  1699. }
  1700. void CodeEditorInterface::paste(C Str &text)
  1701. {
  1702. if(Source *src=CE.cur())
  1703. if(!src->Const && text.is())src->paste(&text);
  1704. }
  1705. C Memx<Item>& CodeEditorInterface::items() {return CE.items;}
  1706. Bool CodeEditorInterface::importPaths ()C {return CE.options.import_path_mode ()>0;}
  1707. Bool CodeEditorInterface::importImageMipMaps()C {return CE.options.import_image_mip_maps() ;}
  1708. void CodeEditorInterface:: play( ) {CE.play();}
  1709. void CodeEditorInterface:: debug( ) {CE.debug();}
  1710. void CodeEditorInterface:: runToCursor( ) {CE.runToCursor();}
  1711. void CodeEditorInterface:: publish( ) {CE.build(BUILD_PUBLISH);}
  1712. void CodeEditorInterface:: build( ) {CE.build();}
  1713. void CodeEditorInterface:: rebuild( ) {CE.rebuild();}
  1714. void CodeEditorInterface::rebuildSymbols( ) {CE.rebuildSymbols(false);}
  1715. void CodeEditorInterface:: clean( ) {CE.clean();}
  1716. void CodeEditorInterface:: cleanAll( ) {CE.cleanAll();}
  1717. void CodeEditorInterface:: stop( ) {CE.killBuild();}
  1718. void CodeEditorInterface:: openIDE( ) {CE.openIDE();}
  1719. void CodeEditorInterface:: exportPaths(Bool relative) {CE.options.export_path_mode.set(relative);}
  1720. Bool CodeEditorInterface:: Export(EXPORT_MODE mode) {if(CE.Export(mode, BUILD_EXPORT)){Explore(CE.build_path); return true;} return false;}
  1721. void CodeEditorInterface::configDebug(Bool debug) { CE.configDebug(debug);}
  1722. Bool CodeEditorInterface::configDebug( ) {return CE.config_debug ;}
  1723. void CodeEditorInterface::config32Bit(Bool bit32) { CE.config32Bit(bit32);}
  1724. Bool CodeEditorInterface::config32Bit( ) {return CE.config_32_bit ;}
  1725. void CodeEditorInterface::configDX9 (Bool dx9 ) { CE.configDX9 (dx9 );}
  1726. Bool CodeEditorInterface::configDX9 ( ) {return CE.config_dx9 ;}
  1727. void CodeEditorInterface::configEXE (EXE_TYPE exe ) { CE.configEXE (exe );}
  1728. EXE_TYPE CodeEditorInterface::configEXE ( ) {return CE.config_exe ;}
  1729. static void DrawPreview(C SourceLoc &loc)
  1730. {
  1731. if(Source *source=CE.getSource(loc))
  1732. {
  1733. source->prepareForDraw();
  1734. D.clip();
  1735. GuiPC gpc;
  1736. gpc.visible =true;
  1737. gpc.enabled =true;
  1738. gpc.clip =CE.sourceRect();
  1739. gpc.client_rect=gpc.clip;
  1740. gpc.offset =gpc.clip.lu();
  1741. gpc.clip.draw(Theme.colors[TOKEN_NONE]);
  1742. gpc.clip.draw(Color(0, 0, 0, 112), false);
  1743. FREPAO(source-> lines).draw(gpc);
  1744. FREPAO(source->view_lines).draw(gpc);
  1745. D.clip();
  1746. }
  1747. }
  1748. void CodeEditorInterface::sourceDrawPreview(C UID &id ) { DrawPreview(id );}
  1749. void CodeEditorInterface::sourceDrawPreview(C Str &name) {CE.init(); DrawPreview(name);} // 'init' in case we're viewing source from data
  1750. void CodeEditorInterface::sourceAuto(C Str &data)
  1751. {
  1752. Source *source=CE.findSource(Str(AutoSource)); if(!source){source=&CE.sources.New(); source->loc.setFile(AutoSource);}
  1753. source->cpp=false;
  1754. source->Const=true;
  1755. source->active=true;
  1756. source->fromText(data);
  1757. }
  1758. void CodeEditorInterface::sourceRemove (C UID &id) {CE.sources.removeData(CE.findSource(id), true);}
  1759. void CodeEditorInterface::sourceOverwrite(C UID &id) {if(Source *source=CE.findSource(id))if(source->modified())source->overwrite();}
  1760. Bool CodeEditorInterface::sourceDataGet(C UID &id, Str &data) {if(Source *source=CE.findSource(id)){ data=source-> asText( ); return true;} data.clear(); return false;}
  1761. Bool CodeEditorInterface::sourceDataSet(C UID &id, C Str &data) {if(Source *source=CE.findSource(id)){source->setUndo(); source->fromText(data); source->undo_original_state=source->undos.undos(); source->forceCreateNextUndo(); return true;} return false;}
  1762. void CodeEditorInterface::kbSet() {if(CE.cur())CE.cur()->kbSet();}
  1763. void CodeEditorInterface::close () {CE.close();}
  1764. void CodeEditorInterface::closeAll()
  1765. {
  1766. Memc<SaveChanges::Elm> elms;
  1767. saveChanges(elms);
  1768. saveChanges(elms, CloseAll);
  1769. }
  1770. void CodeEditorInterface::saveSettings( TextNode &code) {CE.saveSettings(code);}
  1771. void CodeEditorInterface::loadSettings(C TextNode &code) {CE.loadSettings(code);}
  1772. void CodeEditorInterface::clearActiveSources()
  1773. {
  1774. REPA(CE.sources){Source &src=CE.sources[i]; src.was_active=src.active; src.active=false;}
  1775. }
  1776. void CodeEditorInterface::activateSource(C UID &id ) {if(Source *source=CE.getSource(id ))source->active=true;}
  1777. void CodeEditorInterface::activateSource(C Str &name) {if(Source *source=CE.getSource(name))source->active=true;}
  1778. void CodeEditorInterface::activateApp (Bool rebuild_3rd_party_headers)
  1779. {
  1780. // always make sure auto generated header is active
  1781. if(Source *source=CE.findSource(Str(AutoSource)))source->active=true;
  1782. // check if not initialized and opened source became used
  1783. if(!CE.symbols_loaded && CE.cur() && CE.cur()->used())
  1784. {
  1785. CE.init(); // this will rebuild
  1786. }else
  1787. {
  1788. // detect if at least 1 source has different active state
  1789. Bool rebuild=false; REPA(CE.sources){Source &src=CE.sources[i]; if(src.was_active!=src.active){rebuild=true; break;}}
  1790. // rebuild
  1791. if(rebuild || rebuild_3rd_party_headers)CE.rebuildSymbols(rebuild_3rd_party_headers);
  1792. }
  1793. // remove useless sources
  1794. CE.removeUselessSources();
  1795. }
  1796. /******************************************************************************/
  1797. static CChar8 *SupportedVS="Following versions are supported:\nVisual Studio 2015\nVisual Studio 2017 (at least version 15.5)";
  1798. Bool CheckVisualStudio(C VecI4 &vs_ver, Str *message, Bool check_minor)
  1799. {
  1800. if(vs_ver.x<=0){if(message)*message=S+"Visual Studio was not found.\n"+SupportedVS; return false;}
  1801. if(vs_ver.x<14){if(message)*message=S+"Visual Studio version "+vs_ver.asTextDots()+" is no longer supported.\n"+SupportedVS; return false;}
  1802. if(vs_ver.x>15){if(message)*message=S+"Visual Studio version "+vs_ver.asTextDots()+" is not yet supported.\n"+SupportedVS; return false;}
  1803. if(check_minor)
  1804. {
  1805. if(vs_ver.x==15 && vs_ver.y>=0 && vs_ver.y<5){if(message)*message=S+"Visual Studio version "+vs_ver.asTextDots()+" is not supported due to a bug in compiler.\n"+SupportedVS; return false;} // disable VS 2017 ver 15.0 .. 15.4
  1806. }
  1807. if(message)message->clear(); return true;
  1808. }
  1809. static Int Compare(C VisualStudioInstallation &a, C VisualStudioInstallation &b)
  1810. {
  1811. if(Int c=Compare (a.ver , b.ver ))return c;
  1812. if(Int c=CompareNumber (a.name, b.name))return c;
  1813. if(Int c=ComparePathNumber(a.path, b.path))return c;
  1814. return 0;
  1815. }
  1816. Bool GetVisualStudioInstallations(MemPtr<VisualStudioInstallation> installs)
  1817. {
  1818. Bool ok=false;
  1819. installs.clear();
  1820. #if WINDOWS_OLD
  1821. // !! requires 'CoInitialize' !!
  1822. ISetupConfigurationPtr query;
  1823. if(OK(query.CreateInstance(__uuidof(SetupConfiguration))))
  1824. {
  1825. ISetupConfiguration2Ptr query2(query);
  1826. IEnumSetupInstancesPtr e;
  1827. if(OK(query2->EnumAllInstances(&e)))
  1828. {
  1829. ok=true;
  1830. ISetupHelperPtr helper(query);
  1831. ISetupInstance *pInstances[1]={};
  1832. for(; e->Next(1, pInstances, null)==S_OK; )
  1833. {
  1834. ISetupInstance2Ptr instance(pInstances[0]);
  1835. ISetupPackageReferencePtr product;
  1836. InstanceState state;
  1837. bstr_t instance_id, product_id, install_version, display_name, path;
  1838. if(OK(instance->GetInstanceId(instance_id.GetAddress())))
  1839. if(OK(instance->GetState(&state)))
  1840. if(state==eComplete && (eLocal&state)==eLocal && (eRegistered&state)==eRegistered)
  1841. if(OK(instance->GetInstallationVersion(install_version.GetAddress())))
  1842. if(OK(instance->GetInstallationPath(path.GetAddress())))
  1843. if(OK(instance->GetProduct(&product)))
  1844. if(OK(product->GetId(product_id.GetAddress())))
  1845. if(Starts(WChar(product_id.operator const wchar_t*()), "Microsoft.VisualStudio.Product.", true, true))
  1846. {
  1847. #if 0
  1848. bstr_t desc, engine, install_name, product_path, branch, type, version;
  1849. OK(instance->GetDescription(0, desc.GetAddress()));
  1850. OK(instance->GetEnginePath(engine.GetAddress()));
  1851. OK(instance->GetInstallationName(install_name.GetAddress()));
  1852. OK(instance->GetProductPath(product_path.GetAddress()));
  1853. OK(product->GetBranch(branch.GetAddress()));
  1854. OK(product->GetType(type.GetAddress()));
  1855. OK(product->GetVersion(version.GetAddress()));
  1856. #endif
  1857. Char8 temp[256]; Set(temp, WChar(install_version.operator const wchar_t*())); ReplaceSelf(temp, '.', ',');
  1858. VisualStudioInstallation &install=installs.New();
  1859. install.path=path.operator const wchar_t*();
  1860. install.ver =TextVecI4(temp);
  1861. if(OK(instance->GetDisplayName(0, display_name.GetAddress())))install.name=display_name.operator const wchar_t*();
  1862. }
  1863. }
  1864. }
  1865. }
  1866. #if 0
  1867. // older versions were obtained through registry:
  1868. for(Int version=9; version<=..; version++)
  1869. for(Int express=0; express<=1; express++)
  1870. {
  1871. Str path=GetRegStr(RKG_LOCAL_MACHINE, S+"Software/Microsoft/"+(express ? "VCExpress" : "VisualStudio")+'/'+version+".0/Setup/VS/ProductDir");
  1872. if(path.is())
  1873. {
  1874. VisualStudioInstallation &install=installs.New();
  1875. install.path=path;
  1876. install.ver.set(version, 0, 0, 0);
  1877. install.name=S+"Visual Studio "..+(express ? " Express" : null);
  1878. }
  1879. }
  1880. #endif
  1881. installs.sort(Compare);
  1882. #endif
  1883. return ok;
  1884. }
  1885. Str MSBuildPath(C Str &vs_path, C VecI4 &vs_ver)
  1886. {
  1887. if(vs_path.is())
  1888. {
  1889. Str ms_build_path=vs_path; ms_build_path.tailSlash(true)+="MSBuild\\";
  1890. if(vs_ver.x>0)
  1891. {
  1892. Str ms_build=ms_build_path+vs_ver.x+".0\\Bin\\MSBuild.exe";
  1893. //if(FExistSystem(ms_build))
  1894. return ms_build;
  1895. }
  1896. for(FileFind ff(ms_build_path); ff(); )if(ff.type==FSTD_DIR)
  1897. {
  1898. VecI4 ver=TextVecI4(ff.name); if(ver.x>0)return ms_build_path+ver.x+".0\\Bin\\MSBuild.exe";
  1899. }
  1900. }
  1901. Memc<VisualStudioInstallation> installs; if(GetVisualStudioInstallations(installs))REPA(installs) // go from the end to try the latest version first
  1902. {
  1903. VisualStudioInstallation &install=installs[i]; if(CheckVisualStudio(install.ver))
  1904. {
  1905. return install.path.tailSlash(true)+"MSBuild\\"+install.ver.x+".0\\Bin\\MSBuild.exe";
  1906. }
  1907. }
  1908. #if 0 // VS 2015 and older
  1909. {
  1910. Str path=GetRegStr(RKG_LOCAL_MACHINE, S+"Software/Microsoft/MSBuild/ToolsVersions/"+ver+".0/MSBuildToolsPath");
  1911. if( path.is())return path.tailSlash(true)+"MSBuild.exe";
  1912. }
  1913. #endif
  1914. return S;
  1915. }
  1916. Str MSBuildParams(C Str &project, C Str &config, C Str &platform)
  1917. {
  1918. // optional params: /target:clean /target:rebuild /FileLogger /nologo /Verbosity:(quiet, minimal, normal, detailed, or diagnostic) /p:AppxPackageSigningEnabled=false
  1919. return S+'"'+NormalizePath(MakeFullPath(project))+"\" /Verbosity:minimal /nologo"+(config.is() ? S+" /p:Configuration=\""+config+'"' : S)+(platform.is() ? S+" /p:Platform=\""+platform+'"' : S);
  1920. }
  1921. Str VSBuildParams(C Str &project, C Str &config, C Str &platform, C Str &log)
  1922. {
  1923. return S+"/Build \""+config+(platform.is() ? S+'|'+platform : S)+"\" \""+NormalizePath(MakeFullPath(project))+'"'+(log.is() ? S+" /Out \""+NormalizePath(MakeFullPath(log))+'"' : S);
  1924. }
  1925. Str XcodeBuildParams(C Str &project, C Str &config, C Str &platform, C Str &sdk)
  1926. {
  1927. return S+"-project \""+UnixPath(project)+"\" -target \""+platform+"\" -configuration \""+config+'"'+(sdk.is() ? S+" -sdk \""+sdk+"\"" : S);
  1928. }
  1929. Str XcodeBuildCleanParams(C Str &project, C Str &config, C Str &platform, C Str &sdk)
  1930. {
  1931. return S+"clean "+XcodeBuildParams(project, config, platform, sdk);
  1932. }
  1933. Str LinuxBuildParams(C Str &project, C Str &config, Int build_threads)
  1934. {
  1935. return S+(config.is() ? S+"CONF=\""+config+"\" " : S)+"-j"+build_threads+" -C \""+UnixPath(project)+'"';
  1936. }
  1937. /******************************************************************************/
  1938. }}
  1939. /******************************************************************************/