diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..6f413b4e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*.{c,h,d,di,dd}] +end_of_line = crlf +insert_final_newline = true +indent_style = tab +indent_size = 4 +trim_trailing_whitespace = true +charset = utf-8 diff --git a/CHANGES b/CHANGES index e164c007..ad7662f4 100644 --- a/CHANGES +++ b/CHANGES @@ -752,3 +752,34 @@ Version history * installer now shows the version of Visual D about to be installed * mago: added support for new AA implementation * mago: preview for structs now shows first members + +unreleased Version 0.3.43 + + * dustmite: pattern passed to "find" must always use quotes + * VS2015: new install adds $(VCInstallDir)\bin to exectuable paths to allow cv2pdb to create PDB files + * VS2015: added detection for Universal CRT in Win10 SDK, new macro replacements $(UCRTSdkDir) and + $(UCRTVersion) allow adding library search path to find libucrt.lib + * New item: the module name no longer has a preceding '.' when guessing a package name + * when renaming a module in the project, the editor is reopened at the previous caret position if it was + opened before + * replaced ancient pkgcmd.ctc with pkgcmd.vsct that's buildable with newer VS SDKs + * added icons to some commands + * renamed command "Add Folder" in project folder context menu to "Add Filter" + * added command "Add Package" to project folder context menu + * renaming a module in the project tree now reopens it at the previous caret location + * renaming a package in the project tree also renames the folder on disk if it is still empty + * debug info: added option "suitable for selected debug engine" + * the original semantic analysis engine is no longer installed, always using dparser now + * LDC: recent versions build object files into intermediate folder, wrong names passed to linker + with "separate compile and link" + * moved defaults for resource includes and dmd executable paths from installation to extension init + * fixed spurious "not implemented" error in error list + * fix dark theme detection in VS 2015 + * better semantic/colorizer support for versions LDC,CRuntime_Microsoft,CRuntime_DigitalMars and MinGW + * tweaked default path and library settings for DMD and LDC + * configuration dialogs: + - fixed small fonts in VS2015 + - better work with resizeable windows + - scale some controls vertically if there is space + - added browse buttons to path settings + * search pane did not save its last state, only when switching between file and symbol search diff --git a/TODO b/TODO index 3a1d21bd..737002d4 100644 --- a/TODO +++ b/TODO @@ -35,13 +35,19 @@ Project: - ddoc files + additional options for resource compiler - pass import path from static lib project to dependent projects + - single file compilation for file configuration - custom command: quotes in dependencies not supported +- custom command: writes build batch to project folder +- custom command: no output given => creates ".build.cmd" +- single file commands: track dependencies +- single file commands: multiple outputs + - VS2013: property pages don't follow resize -- custom command: writes build batch to source folder - VS2013: possible to copy a project item with DnD into the same project again - saving file while it is being compiled/linked does not force a recompilation + Language service: ----------------- + goto definition does not know about scope @@ -82,6 +88,7 @@ Semantics: - vdserver.exe should terminate if devenv.exe crashes - expansion fails too often - handle parser error at caret better for expansion/definition +- ddmd: semantic engine fails when module names do not match the path? Search: --------------- @@ -92,6 +99,7 @@ Search: - update result list after build - update too slow when typing filter - VS2012: focus not in edit line after opening dialog +- ddmd: finding files in .. does not work? Object Browser: --------------- @@ -135,7 +143,7 @@ Any/dmd: Mago: -- show derived class +- ddmd: show derived class - step after exception - exceptions on x64 + set instruction pointer @@ -163,6 +171,7 @@ Mago: - attach to process - hardware breakpoints + does not work with variable scope +- ddmd: ignore keywords in (C++) expressions VS: - VS2012: autoexp.dat does not work? depends on debug engine => edit and continue @@ -211,3 +220,4 @@ Unsorted + run cv2pdb disabled for GDC/x64 - hide Visual D menu if inactive +- follow theme colors for tool windows diff --git a/VERSION b/VERSION index 9cf83c97..28246440 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ #define VERSION_MAJOR 0 #define VERSION_MINOR 3 -#define VERSION_REVISION 42 -#define VERSION_BETA -#define VERSION_BUILD 0 +#define VERSION_REVISION 43 +#define VERSION_BETA -beta +#define VERSION_BUILD 1 diff --git a/c2d/idl2d.d b/c2d/idl2d.d index e490bcba..195c85d4 100644 --- a/c2d/idl2d.d +++ b/c2d/idl2d.d @@ -10,7 +10,7 @@ // // idl2d - convert IDL or header files to D // -// +// // module c2d.idl2d; @@ -84,10 +84,10 @@ class idl2d string win_path = r"c:\Program Files\Microsoft SDKs\Windows\v7.1\Include\"; string sdk_d_path = r"c:\s\d\visuald\trunk\sdk\"; } - + static const string dirVSI = "vsi"; static const string dirWin = "win32"; - + string packageVSI = "sdk." ~ dirVSI ~ "."; string packageWin = "sdk." ~ dirWin ~ "."; string packageNF = "sdk.port."; @@ -103,36 +103,36 @@ class idl2d string[] vsi_idl_files; string[] vsi_h_files; string[] dte_idl_files; - + version(vsi) bool vsi = true; else bool vsi = false; - + void initFiles() { - win_idl_files = [ "windef.h", "sdkddkver.h", "basetsd.h", "ntstatus.h", - "winnt.h", "winbase.h", "winuser.h", "ktmtypes.h", + win_idl_files = [ "windef.h", "sdkddkver.h", "basetsd.h", "ntstatus.h", + "winnt.h", "winbase.h", "winuser.h", "ktmtypes.h", "winerror.h", "winreg.h", "reason.h", "commctrl.h", - "wingdi.h", "prsht.h", + "wingdi.h", "prsht.h", "iphlpapi.h", "iprtrmib.h", "ipexport.h", "iptypes.h", "tcpestats.h", /*"inaddr.h", "in6addr.h",*/ "ipifcons.h", "ipmib.h", "tcpmib.h", "udpmib.h", "ifmib.h", "ifdef.h", "nldef.h", "winnls.h", "shellapi.h", "rpcdce.h" /*, "rpcdcep.h"*/ ]; - - win_idl_files ~= [ "unknwn.idl", "oaidl.idl", "wtypes.idl", "oleidl.idl", + + win_idl_files ~= [ "unknwn.idl", "oaidl.idl", "wtypes.idl", "oleidl.idl", "ocidl.idl", "objidl.idl", "docobj.idl", "oleauto.h", "objbase.h", "mshtmcid.h", "xmldom.idl", "xmldso.idl", "xmldomdid.h", "xmldsodid.h", "idispids.h", "activdbg.id*", "activscp.id*", "dbgprop.id*", // only available in Windows SDK v7.x ]; // only available (and are required for successfull compilation) in Windows SDK v8 - foreach(f; [ "wtypesbase.idl", + foreach(f; [ "wtypesbase.idl", //"winapifamily.h", "apisetcconv.h", "apiset.h", // commented because it is difficult to convert this file - "minwinbase.h", "processenv.h", + "minwinbase.h", "processenv.h", "minwindef.h", "fileapi.h", "debugapi.h", "handleapi.h", "errhandlingapi.h", "fibersapi.h", "namedpipeapi.h", "profileapi.h", "heapapi.h", "synchapi.h", - "interlockedapi.h", "processthreadsapi.h", "sysinfoapi.h", "memoryapi.h", - "threadpoollegacyapiset.h", "utilapiset.h", "ioapiset.h", + "interlockedapi.h", "processthreadsapi.h", "sysinfoapi.h", "memoryapi.h", + "threadpoollegacyapiset.h", "utilapiset.h", "ioapiset.h", "threadpoolprivateapiset.h", "threadpoolapiset.h", "bemapiset.h", "wow64apiset.h", "jobapi.h", "timezoneapi.h", "datetimeapi.h", "stringapiset.h", "libloaderapi.h", "securitybaseapi.h", "namespaceapi.h", "systemtopologyapi.h", "processtopologyapi.h", @@ -150,9 +150,9 @@ class idl2d "vsdebugguids.h", "VSRegKeyNames.h", "SCGuids.h", "wbids.h", "sharedids.h", "vseeguids.h", "version.h", "scc.h", "vsplatformuiuuids.*", // only in VS2010 SDK - // no longer in SDK2010: "DSLToolsCmdID.h", + // no longer in SDK2010: "DSLToolsCmdID.h", ]; - + dte_idl_files = [ "*.idl" ]; } } @@ -207,7 +207,7 @@ class idl2d assert(it[2].type == Token.String); assert(it[3].text == ")"); string text = strip(it[2].text[1..$-1]); - + string txt = text; bool convert = convert_next_cpp_quote; convert_next_cpp_quote = true; @@ -229,7 +229,7 @@ class idl2d txt = replace(txt, "\\\"", "\""); txt = convertPP(txt, tokIt.lineno, inEnum); } - + if(convert) { string pretext = tokIt.pretext; @@ -318,16 +318,16 @@ class idl2d if(vsi) goto default; return !first; - + case Token.Comma: return !first && !(tokIt + 1).atEnd() && tokIt[1].type != Token.EOF; - + case Token.Struct: // struct at beginning of a cast? if(!tokIt.atBegin() && tokIt[-1].type == Token.ParenL) return true; return false; - + default: return false; } @@ -404,7 +404,7 @@ class idl2d { case "FALSE": return -2; // not defined for expression, but for #define - + case "_WIN64": return 4; // special cased case "0": @@ -431,7 +431,7 @@ class idl2d case "RGS_INVOKED": case "__RE_E_DEFINED__": case "OLE2ANSI": - + // for winbase case "STRICT": case "_M_CEE": @@ -460,9 +460,9 @@ class idl2d case "TRUE": return 2; // predefined for expression, but not for #define case "1": - case "__cplusplus": - case "UNICODE": - case "DEFINE_GUID": + case "__cplusplus": + case "UNICODE": + case "DEFINE_GUID": case "UNIX": case "_X86_": case "_M_IX86": @@ -536,12 +536,12 @@ class idl2d case "MF_END": // defined twice in winuser.h, but said to be obsolete case "__int3264": return 1; - + case "_NO_SCRIPT_GUIDS": // used in activdbg.h, disable to avoid duplicate GUID definitions case "EnumStackFramesEx": // used in activdbg.h, but in wrong scope case "SynchronousCallIntoThread": // used in activdbg.h, but in wrong scope return 1; - + // winnt.h case "_WINDEF_": case "_WINBASE_": @@ -556,7 +556,7 @@ class idl2d // Windows SDK 8.0 case "_CONTRACT_GEN": return -1; - default: + default: break; } @@ -930,7 +930,7 @@ version(none){ { if(it != tokIt + 1 && it != tokIt + 2 && it != tokIt + 3) { - if(endIt == tokIt + 3 && tokIt[2].type == Token.Identifier && + if(endIt == tokIt + 3 && tokIt[2].type == Token.Identifier && !(tokIt[2].text in enums) && tokIt[2].text != "NULL") { if(tokIt[2].text in disabled_defines) @@ -968,7 +968,7 @@ version(none){ } else tokIt.pretext ~= "// "; - + Token tok = createToken("", ";", Token.Comma, tokIt.lineno); endIt.insertBefore(tok); if(!inDisabledPPBranch()) @@ -994,7 +994,7 @@ version(none){ if(!advanceToClosingBracket(it)) return; } -version(all) +version(all) { tokIt.insertBefore(createToken("", "/", Token.Div, tokIt.lineno)); tokIt.insertBefore(createToken("", "+", Token.Plus, tokIt.lineno)); @@ -1090,8 +1090,8 @@ version(all) { // tokIt after "{" static bool numberOrIdent(Token tok) - { - return tok.type == Token.Identifier || tok.type == Token.Number; + { + return tok.type == Token.Identifier || tok.type == Token.Number; } static string toByteArray(string txt) { @@ -1116,7 +1116,7 @@ version(all) tokIt[0].text = "0x" ~ tokIt[0].text; tokIt[1].text = ","; tokIt[2].text = "0x" ~ tokIt[2].text; tokIt[3].text = ","; tokIt[4].text = "0x" ~ tokIt[4].text; tokIt[5].text = ","; - + tokIt[6].text = "[ " ~ toByteArray(tokIt[6].text); tokIt[7].text = ","; tokIt[8].text = toByteArray(tokIt[8].text) ~ " ]"; } @@ -1146,8 +1146,8 @@ version(all) break; if (i >= 8) { - tokIt[6].pretext = " [" ~ tokIt[6].pretext; - tokIt[21].pretext = " ]" ~ tokIt[21].pretext; + tokIt[6].pretext = " [" ~ tokIt[6].pretext; + tokIt[21].pretext = " ]" ~ tokIt[21].pretext; } } } @@ -1157,7 +1157,7 @@ version(all) // "af855397-c4dc-478b-abd4-c3dbb3759e72" if(txt.length == 38 && txt[9] == '-' && txt[14] == '-' && txt[19] == '-' && txt[24] == '-') { - tokIt.text = "0x" ~ txt[1..9] ~ ", 0x" ~ txt[10..14] ~ ", 0x" ~ txt[15..19] ~ ", [ " + tokIt.text = "0x" ~ txt[1..9] ~ ", 0x" ~ txt[10..14] ~ ", 0x" ~ txt[15..19] ~ ", [ " ~ "0x" ~ txt[20..22] ~ ", 0x" ~ txt[22..24]; for(int i = 0; i < 6; i++) tokIt.text ~= ", 0x" ~ txt[25 + 2*i .. 27 + 2*i]; @@ -1248,7 +1248,7 @@ version(all) replaceTokenSequence(tokens, "WINOLEAPI_($_rettype)", "extern(Windows) $_rettype", true); replaceTokenSequence(tokens, "WINOLEAPI", "extern(Windows) HRESULT", true); replaceTokenSequence(tokens, "$_ident WINAPIV", "extern(C) $_ident", true); - + replaceTokenSequence(tokens, "RPCRTAPI", "export", true); replaceTokenSequence(tokens, "RPC_STATUS", "int", true); replaceTokenSequence(tokens, "RPC_ENTRY", "extern(Windows)", true); @@ -1262,7 +1262,7 @@ version(all) replaceTokenSequence(tokens, "UNREFERENCED_PARAMETER($arg);", "/*UNREFERENCED_PARAMETER($arg);*/", true); if(currentModule == "rpcdce") { - replaceTokenSequence(tokens, "RPC_INTERFACE_GROUP_IDLE_CALLBACK_FN($args);", + replaceTokenSequence(tokens, "RPC_INTERFACE_GROUP_IDLE_CALLBACK_FN($args);", "function($args) RPC_INTERFACE_GROUP_IDLE_CALLBACK_FN;", true); } // windef.h and ktmtypes.h @@ -1290,9 +1290,9 @@ version(all) // imports inside extern(C) {} replaceTokenSequence(tokens, "extern \"C\" { $_data }", "$_data", true); } - + // select unicode version of the API when defining without postfix A/W - replaceTokenSequence(tokens, "#ifdef UNICODE\nreturn $_identW(\n#else\nreturn $_identA(\n#endif\n", + replaceTokenSequence(tokens, "#ifdef UNICODE\nreturn $_identW(\n#else\nreturn $_identA(\n#endif\n", " return $_identW(", false); replaceTokenSequence(tokens, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n", "extern \"C\" {\n", false); @@ -1310,16 +1310,16 @@ version(all) parenCount++; break; case ")": - parenCount--; + parenCount--; break; case "[": - brackCount++; + brackCount++; break; - case "]": + case "]": brackCount--; break; case "{": - braceCount++; + braceCount++; break; case "}": braceCount--; @@ -1384,7 +1384,7 @@ version(all) case "short": t = "ushort"; break; case "char": t = "ubyte"; break; default: - t = "uint"; + t = "uint"; skipNext = false; break; } @@ -1407,7 +1407,7 @@ version(all) case "short": t = "short"; break; case "char": t = "byte"; break; default: - t = "int"; + t = "int"; skipNext = false; break; } @@ -1460,8 +1460,8 @@ version(all) // in function argument //if(tok.text == "const" || tok.text == "CONST") // tok.text = "/*const*/"; - //else - if (tok.text.startsWith("REF") && + //else + if (tok.text.startsWith("REF") && tok.text != "REFSHOWFLAGS" && !tok.text.startsWith("REFERENCE")) { tokIt.insertBefore(createToken(tok.pretext, "ref", Token.Identifier, tokIt.lineno)); @@ -1488,7 +1488,7 @@ version(none) version(vsi) replaceTokenSequence(tokens, "typedef char OLECHAR;", "typedef char idl_OLECHAR;", true); replaceTokenSequence(tokens, "typedef LPSTR LPOLESTR;", "typedef LPSTR idl_LPOLESTR;", true); replaceTokenSequence(tokens, "typedef LPCSTR LPCOLESTR;", "typedef LPCSTR idl_LPCOLESTR;", true); - + replaceTokenSequence(tokens, "WCHAR OLECHAR;", "WCHAR idl_OLECHAR;", true); replaceTokenSequence(tokens, "OLECHAR *LPOLESTR;", "OLECHAR *idl_LPOLESTR;", true); replaceTokenSequence(tokens, "const OLECHAR *LPCOLESTR;", "OLECHAR *idl_LPCOLESTR;", true); @@ -1496,7 +1496,7 @@ version(none) version(vsi) replaceTokenSequence(tokens, "typedef LONG SCODE;", "typedef LONG vsi_SCODE;", true); } - //replaceTokenSequence(tokens, "interface IWinTypes { $data }", + //replaceTokenSequence(tokens, "interface IWinTypes { $data }", // "/+interface IWinTypes {+/\n$data\n/+ } /+IWinTypes+/ +/", true); // docobj.idl (v6.0a) @@ -1509,7 +1509,7 @@ version(none) version(vsi) // win SDK 8.1: double define replaceTokenSequence(tokens, "typedef struct tagPAGESET {} PAGESET;", "", true); } - + //vsshell.idl if(currentModule == "vsshell") { @@ -1521,11 +1521,11 @@ version(none) version(vsi) { replaceTokenSequence(tokens, "MENUEDITOR_TRANSACTION_ALL,", "MENUEDITOR_TRANSACTION_ALL = 0,", true); // overflow from -1u } - + // vslangproj90.idl if(currentModule == "vslangproj90") replaceTokenSequence(tokens, "CsharpProjectConfigurationProperties3", "CSharpProjectConfigurationProperties3", true); - + if(currentModule == "msdbg") replaceTokenSequence(tokens, "const DWORD S_UNKNOWN = 0x3;", "denum DWORD S_UNKNOWN = 0x3;", true); if(currentModule == "activdbg") @@ -1554,7 +1554,7 @@ version(none) version(vsi) if(currentModule == "ocidl") { // move alias out of interface declaration, it causes circular definitions with dmd 2.065+ - replaceTokenSequence(tokens, "interface IOleUndoManager : IUnknown { alias IID_IOleUndoManager SID_SOleUndoManager; $data }", + replaceTokenSequence(tokens, "interface IOleUndoManager : IUnknown { alias IID_IOleUndoManager SID_SOleUndoManager; $data }", "interface IOleUndoManager : IUnknown { $data }\n\nalias IID_IOleUndoManager SID_SOleUndoManager;", true); } @@ -1575,7 +1575,7 @@ version(none) version(vsi) version(remove_pp) { string tsttxt = tokenListToString(tokens); - + while(replaceTokenSequence(tokens, "$_note else version(all) { $if } else { $else }", "$_note $if", true) > 0 || replaceTokenSequence(tokens, "$_note else version(all) { $if } else version($ver) { $else_ver } else { $else }", "$_note $if", true) > 0 || replaceTokenSequence(tokens, "$_note else version(all) { $if } $_not else", "$_note $if\n$_not", true) > 0 || @@ -1584,13 +1584,13 @@ version(remove_pp) replaceTokenSequence(tokens, "version(pp_if) { $if } else { $else }", "$else", true) > 0 || replaceTokenSequence(tokens, "version(pp_if) { $if } $_not else", "$_not", true) > 0 || replaceTokenSequence(tokens, "version(pp_ifndef) { $if } else { $else }", "$if", true) > 0 || - replaceTokenSequence(tokens, "version(pp_ifndef) { $if } $_not else", "$if\n$_not", true) > 0) + replaceTokenSequence(tokens, "version(pp_ifndef) { $if } $_not else", "$if\n$_not", true) > 0) { string rtsttxt = tokenListToString(tokens); } string ntsttxt = tokenListToString(tokens); - + } while(replaceTokenSequence(tokens, "static if($expr) { } else { }", "", true) > 0 || @@ -1599,61 +1599,61 @@ version(remove_pp) replaceTokenSequence(tokens, "version($expr) { } $_not else", "$_not", true) > 0) {} // move declaration at the top of the interface below the interface while keeping the order - replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { $data }", + replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { $data }", "interface $_ident1 : $_identbase { $data\n} __eo_interface", true); - while(replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { typedef $args; $data } $tail __eo_interface", + while(replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { typedef $args; $data } $tail __eo_interface", "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\ntypedef $args; __eo_interface", true) > 0 - || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { denum $args; $data } $tail __eo_interface", + || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { denum $args; $data } $tail __eo_interface", "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\ndenum $args; __eo_interface", true) > 0 - || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { enum $args; $data } $tail __eo_interface", + || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { enum $args; $data } $tail __eo_interface", "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nenum $args; __eo_interface", true) > 0 - || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { dconst $_ident = $expr; $data } $tail __eo_interface", + || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { dconst $_ident = $expr; $data } $tail __eo_interface", "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\ndconst $_ident = $expr; __eo_interface", true) > 0 - || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { const $_identtype $_ident = $expr; $data } $tail __eo_interface", + || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { const $_identtype $_ident = $expr; $data } $tail __eo_interface", "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nconst $_identtype $_ident = $expr; __eo_interface", true) > 0 - || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { const $_identtype *$_ident = $expr; $data } $tail __eo_interface", + || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { const $_identtype *$_ident = $expr; $data } $tail __eo_interface", "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nconst $_identtype *$_ident = $expr; __eo_interface", true) > 0 - || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { struct $args; $data } $tail __eo_interface", + || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { struct $args; $data } $tail __eo_interface", "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nstruct $args; __eo_interface", true) > 0 - || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { union $args; $data } $tail __eo_interface", + || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { union $args; $data } $tail __eo_interface", "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nunion $args; __eo_interface", true) > 0 - || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { static if($expr) { $if } else { $else } $data } $tail __eo_interface", + || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { static if($expr) { $if } else { $else } $data } $tail __eo_interface", "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nstatic if($expr) {\n$if\n} else {\n$else\n} __eo_interface", true) > 0 - || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { version($expr) {/+ typedef $if } else { $else } $data } $tail __eo_interface", + || replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { version($expr) {/+ typedef $if } else { $else } $data } $tail __eo_interface", "interface $_ident1 : $_identbase\n{ $data\n}\n$tail\nversion($expr) {/+\ntypedef $if\n} else {\n$else\n} __eo_interface", true) > 0 ) {} replaceTokenSequence(tokens, "__eo_interface", "", true); - replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { $data const DISPID $constids }", + replaceTokenSequence(tokens, "interface $_ident1 : $_identbase { $data const DISPID $constids }", "interface $_ident1 : $_identbase { $data\n}\n\nconst DISPID $constids\n", true); version(none) { - replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $_ident2;", + replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $_ident2;", "enum $_ident2\n{\n$enums\n}", true); - replaceTokenSequence(tokens, "typedef enum { $enums } $_ident2;", + replaceTokenSequence(tokens, "typedef enum { $enums } $_ident2;", "enum $_ident2\n{\n$enums\n}", true); - replaceTokenSequence(tokens, "typedef [$_ident3] enum $_ident1 { $enums } $_ident2;", + replaceTokenSequence(tokens, "typedef [$_ident3] enum $_ident1 { $enums } $_ident2;", "enum $_ident2\n{\n$enums\n}", true); - replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef $_identbase $_ident2;", + replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef $_identbase $_ident2;", "enum $_ident2 : $_identbase\n{\n$enums\n}", true); } else { - replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $_ident1;", + replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $_ident1;", "enum /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;", true); - replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $ident2;", + replaceTokenSequence(tokens, "typedef enum $_ident1 { $enums } $ident2;", "enum /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;\ntypedef int $ident2;", true); - replaceTokenSequence(tokens, "typedef enum { $enums } $ident2;", + replaceTokenSequence(tokens, "typedef enum { $enums } $ident2;", "enum\n{\n$enums\n}\ntypedef int $ident2;", true); - replaceTokenSequence(tokens, "typedef [$info] enum $_ident1 { $enums } $_ident1;", + replaceTokenSequence(tokens, "typedef [$info] enum $_ident1 { $enums } $_ident1;", "enum [$info] /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;", true); - replaceTokenSequence(tokens, "typedef [$info] enum $_ident1 { $enums } $ident2;", + replaceTokenSequence(tokens, "typedef [$info] enum $_ident1 { $enums } $ident2;", "enum [$info] /+$_ident1+/\n{\n$enums\n}\ntypedef int $_ident1;\ntypedef int $ident2;", true); - replaceTokenSequence(tokens, "typedef [$info] enum { $enums } $ident2;", + replaceTokenSequence(tokens, "typedef [$info] enum { $enums } $ident2;", "enum [$info]\n{\n$enums\n}\ntypedef int $ident2;", true); - replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef $_identbase $_ident2;", + replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef $_identbase $_ident2;", "enum /+$_ident1+/ : $_identbase \n{\n$enums\n}\ntypedef $_identbase $_ident1;\ntypedef $_identbase $_ident2;", true); - replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef [$info] $_identbase $_ident2;", + replaceTokenSequence(tokens, "enum $_ident1 { $enums }; typedef [$info] $_identbase $_ident2;", "enum /+$_ident1+/ : $_identbase \n{\n$enums\n}\ntypedef [$info] $_identbase $_ident2;", true); - replaceTokenSequence(tokens, "enum $_ident1 { $enums };", + replaceTokenSequence(tokens, "enum $_ident1 { $enums };", "enum /+$_ident1+/ : int \n{\n$enums\n}\ntypedef int $_ident1;", true); replaceTokenSequence(tokens, "typedef enum $_ident1 $_ident1;", "/+ typedef enum $_ident1 $_ident1; +/", true); replaceTokenSequence(tokens, "enum $_ident1 $_ident2", "$_ident1 $_ident2", true); @@ -1663,21 +1663,21 @@ version(none) replaceTokenSequence(tokens, "__struct_bcount($args)", "[__struct_bcount($args)]", true); replaceTokenSequence(tokens, "struct $_ident : $_opt public $_ident2 {", "struct $_ident { $_ident2 base;", true); - replaceTokenSequence(tokens, "typedef struct { $data } $_ident2;", + replaceTokenSequence(tokens, "typedef struct { $data } $_ident2;", "struct $_ident2\n{\n$data\n}", true); - replaceTokenSequence(tokens, "typedef struct { $data } $_ident2, $expr;", + replaceTokenSequence(tokens, "typedef struct { $data } $_ident2, $expr;", "struct $_ident2\n{\n$data\n}\ntypedef $_ident2 $expr;", true); - replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } $_ident2;", + replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } $_ident2;", "struct $_ident1\n{\n$data\n}\ntypedef $_ident1 $_ident2;", true); - replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } $expr;", + replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } $expr;", "struct $_ident1\n{\n$data\n}\ntypedef $_ident1 $expr;", true); - replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 { $data } $expr;", + replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 { $data } $expr;", "[$props] struct $_ident1\n{\n$data\n}\ntypedef $_ident1 $expr;", true); - //replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } *$_ident2;", + //replaceTokenSequence(tokens, "typedef struct $_ident1 { $data } *$_ident2;", // "struct $_ident1\n{\n$data\n}\ntypedef $_ident1 *$_ident2;", true); - //replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 { $data } *$_ident2;", + //replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 { $data } *$_ident2;", // "[$props] struct $_ident1\n{\n$data\n}\ntypedef $_ident1 *$_ident2;", true); - while(replaceTokenSequence(tokens, "struct { $data } $_ident2 $expr;", + while(replaceTokenSequence(tokens, "struct { $data } $_ident2 $expr;", "struct _ __ $_ident2 {\n$data\n} _ __ $_ident2 $_ident2 $expr;", true) > 0) {} replaceTokenSequence(tokens, "[$_expr1 uuid($_identIID) $_expr2] interface $_identClass : $_identBase {", @@ -1697,7 +1697,7 @@ version(none) // replaceTokenSequence(tokens, "assert $expr;", "assert($expr);", true); - replaceTokenSequence(tokens, "typedef union $_ident1 { $data } $_ident2 $expr;", + replaceTokenSequence(tokens, "typedef union $_ident1 { $data } $_ident2 $expr;", "union $_ident1\n{\n$data\n}\ntypedef $_ident1 $_ident2 $expr;", true); replaceTokenSequence(tokens, "typedef union $_ident1 switch($expr) $_ident2 { $data } $_ident3;", "union $_ident3 /+switch($expr) $_ident2 +/ { $data };", true); @@ -1709,55 +1709,46 @@ version(none) "union $_ident1 /+switch($expr) $_ident2 +/ { $data }", true); replaceTokenSequence(tokens, "case $_ident1:", "[case $_ident1:]", true); replaceTokenSequence(tokens, "default:", "[default:]", true); - replaceTokenSequence(tokens, "union { $data } $_ident2 $expr;", + replaceTokenSequence(tokens, "union { $data } $_ident2 $expr;", "union _ __ $_ident2 {\n$data\n} _ __ $_ident2 $_ident2 $expr;", true); replaceTokenSequence(tokens, "typedef struct $_ident1 $expr;", "typedef $_ident1 $expr;", true); replaceTokenSequence(tokens, "typedef [$props] struct $_ident1 $expr;", "typedef [$props] $_ident1 $expr;", true); - while (replaceTokenSequence(tokens, "typedef __nullterminated CONST $_identtype $_expr1, $args;", + while (replaceTokenSequence(tokens, "typedef __nullterminated CONST $_identtype $_expr1, $args;", "typedef __nullterminated CONST $_identtype $_expr1; typedef __nullterminated CONST $_identtype $args;", true) > 0) {} - while (replaceTokenSequence(tokens, "typedef CONST $_identtype $_expr1, $args;", + while (replaceTokenSequence(tokens, "typedef CONST $_identtype $_expr1, $args;", "typedef CONST $_identtype $_expr1; typedef CONST $_identtype $args;", true) > 0) {} - while (replaceTokenSequence(tokens, "typedef __nullterminated $_identtype $_expr1, $args;", + while (replaceTokenSequence(tokens, "typedef __nullterminated $_identtype $_expr1, $args;", "typedef __nullterminated $_identtype $_expr1; typedef __nullterminated $_identtype $args;", true) > 0) {} - while (replaceTokenSequence(tokens, "typedef [$info] $_identtype $_expr1, $args;", + while (replaceTokenSequence(tokens, "typedef [$info] $_identtype $_expr1, $args;", "typedef [$info] $_identtype $_expr1; typedef [$info] $_identtype $args;", true) > 0) {} - while (replaceTokenSequence(tokens, "typedef /+$info+/ $_identtype $_expr1, $args;", + while (replaceTokenSequence(tokens, "typedef /+$info+/ $_identtype $_expr1, $args;", "typedef /+$info+/ $_identtype $_expr1; typedef /+$info+/ $_identtype $args;", true) > 0) {} - while (replaceTokenSequence(tokens, "typedef $_identtype $_expr1, $args;", + while (replaceTokenSequence(tokens, "typedef $_identtype $_expr1, $args;", "typedef $_identtype $_expr1; typedef $_identtype $args;", true) > 0) {} - while (replaceTokenSequence(tokens, "typedef void $_expr1, $args;", + while (replaceTokenSequence(tokens, "typedef void $_expr1, $args;", "typedef void $_expr1; typedef void $args;", true) > 0) {}; replaceTokenSequence(tokens, "typedef $_ident1 $_ident1;", "", true); replaceTokenSequence(tokens, "typedef interface $_ident1 $_ident1;", "", true); - + // Remote/Local version are made final to avoid placing them into the vtbl replaceTokenSequence(tokens, "[$pre call_as($arg) $post] $_not final", "[$pre call_as($arg) $post] final $_not", true); // Some properties use the same name as the type of the return value replaceTokenSequence(tokens, "$_identFun([$data] $_identFun $arg)", "$_identFun([$data] .$_identFun $arg)", true); - if(startsWith(currentModule, "dte")) - { - // more complications in dte*.idl - replaceTokenSequence(tokens, "$_identFun($_identFun $arg)", "$_identFun(.$_identFun $arg)", true); - replaceTokenSequence(tokens, "$_identFun($arg1, [$data] $_identFun $arg)", - "$_identFun($arg1, [$data] .$_identFun $arg)", true); - replaceTokenSequence(tokens, "$_identFun($arg1, $arg2, [$data] $_identFun $arg)", - "$_identFun($arg1, $arg2, [$data] .$_identFun $arg)", true); - replaceTokenSequence(tokens, "$_not . DTE*", "$_not . DTE*", true); - replaceTokenSequence(tokens, "$_not . TextRanges*", "$_not . TextRanges*", true); - replaceTokenSequence(tokens, "$_not . Breakpoints*", "$_not . Breakpoints*", true); - replaceTokenSequence(tokens, "$_not . UIHierarchyItems*", "$_not . UIHierarchyItems*", true); - replaceTokenSequence(tokens, "Collection([$data] ProjectItems $arg)", "Collection([$data] .ProjectItems $arg)", true); - } - if(currentModule == "dte80a") - { - replaceTokenSequence(tokens, "[id($_num), propputref $attr] HRESULT Value", "[id($_num), propputref $attr]\nHRESULT putref_Value", true); - } + // properties that have identically named getter and setter methods have reversed vtbl entries, + // so we prepend put_,get_ or putref_ to the property + if(startsWith(currentModule, "debugger80")) + replaceTokenSequence(tokens, "HRESULT _stdcall", "HRESULT", true); // confusing following rules + + replaceTokenSequence(tokens, "[$attr1 propput $attr2] HRESULT $_identFun", "[$attr1 propput $attr2]\n\tHRESULT put_ __ $_identFun", true); + replaceTokenSequence(tokens, "[$attr1 propget $attr2] HRESULT $_identFun", "[$attr1 propget $attr2]\n\tHRESULT get_ __ $_identFun", true); + replaceTokenSequence(tokens, "[$attr1 propputref $attr2] HRESULT $_identFun", "[$attr1 propputref $attr2]\n\tHRESULT putref_ __ $_identFun", true); + // VS2012 SDK if(currentModule == "webproperties") { @@ -1778,13 +1769,13 @@ version(none) } // interface without base class is used as namespace - replaceTokenSequence(tokens, "interface $_notIFace IUnknown { $_not static $data }", + replaceTokenSequence(tokens, "interface $_notIFace IUnknown { $_not static $data }", "/+interface $_notIFace {+/ $_not $data /+} interface $_notIFace+/", true); replaceTokenSequence(tokens, "dispinterface $_ident1 { $data }", "interface $_ident1 { $data }", true); replaceTokenSequence(tokens, "module $_ident1 { $data }", "/+module $_ident1 {+/ $data /+}+/", true); replaceTokenSequence(tokens, "properties:", "/+properties:+/", true); replaceTokenSequence(tokens, "methods:", "/+methods:+/", true); - + replaceTokenSequence(tokens, "(void)", "()", true); replaceTokenSequence(tokens, "(VOID)", "()", true); replaceTokenSequence(tokens, "[in] ref $_ident", "in $_ident*", true); // in passes by value otherwise @@ -1799,7 +1790,7 @@ version(none) replaceExpressionTokens(tokens); replaceTokenSequence(tokens, "__success($args)", "/+__success($args)+/", true); - + version(all) { replaceTokenSequence(tokens, "typedef const", "typedef CONST", true); replaceTokenSequence(tokens, "extern \"C\"", "extern(C)", true); @@ -1825,7 +1816,7 @@ version(all) { replaceTokenSequence(tokens, "__out_data_source($args)", "/+$*+/", true); replaceTokenSequence(tokens, "__out_xcount_opt($args)", "/+$*+/", true); replaceTokenSequence(tokens, "__out_has_type_adt_props($args)", "/+$*+/", true); - + replaceTokenSequence(tokens, "__inout_bcount($args)", "/+$*+/", true); replaceTokenSequence(tokens, "__inout_ecount($args)", "/+$*+/", true); replaceTokenSequence(tokens, "__inout_xcount($args)", "/+$*+/", true); @@ -1859,7 +1850,7 @@ version(all) { replaceTokenSequence(tokens, "__drv_freesMem($args)", "/+$*+/", true); replaceTokenSequence(tokens, "__drv_preferredFunction($args)", "/+$*+/", true); replaceTokenSequence(tokens, "__drv_allocatesMem($args)", "/+$*+/", true); - + // Win SDK 8.0 replaceTokenSequence(tokens, "_IRQL_requires_same_", "/+$*+/", true); replaceTokenSequence(tokens, "_Function_class_($args)", "/+$*+/", true); @@ -1957,7 +1948,7 @@ version(all) { replaceTokenSequence(tokens, "$_identtype (extern(Windows)", "extern(Windows) $_identtype (", true); replaceTokenSequence(tokens, "$_identtype* (extern(Windows)", "extern(Windows) $_identtype* (", true); replaceTokenSequence(tokens, "$_identtype (/+$_ident+/ extern(Windows)", "extern(Windows) $_identtype (", true); - + replaceTokenSequence(tokens, "DECLARE_HANDLE($_ident);", "typedef HANDLE $_ident;", true); replaceTokenSequence(tokens, "__inline $_identFun(", "inline int $_identFun(", true); @@ -1981,7 +1972,7 @@ else replaceTokenSequence(tokens, "const $_ident*", "/+const+/ $_ident*", true); } replaceTokenSequence(tokens, "in const $_not(", "in $_not", false); - + if(currentModule == "vsshelluuids") { @@ -1994,7 +1985,7 @@ else { replaceTokenSequence(tokens, "denum icmdHelpManager = $data; denum icmdHelpManager", "denum icmdHelpManager", true); } - + if(currentModule == "prsht") { replaceTokenSequence(tokens, "alias _PROPSHEETPAGEA $_ident;", "alias $_ident _PROPSHEETPAGEA;", true); @@ -2029,7 +2020,7 @@ else } else if(tok.text == "[" && tokIt[1].text != "]") { - if((tokIt.atBegin() || tokIt[-1].text != "{" || tokIt[-2].text != "=") && + if((tokIt.atBegin() || tokIt[-1].text != "{" || tokIt[-2].text != "=") && (tokIt[1].type != Token.Number || tokIt[2].text != "]") && (tokIt[2].text != "]" || tokIt[3].text != ";")) { @@ -2046,7 +2037,7 @@ else else if(tok.text == "]" && tokIt[-1].text != "[") { TokenIterator openit = tokIt; - if(retreatToOpeningBracket(openit) && + if(retreatToOpeningBracket(openit) && (openit.atBegin || (openit-1).atBegin || openit[-1].text != "{" || openit[-2].text != "=")) if((tokIt[-1].type != Token.Number || tokIt[-2].text != "[") && (tokIt[-2].text != "[" || tokIt[1].text != ";")) @@ -2062,7 +2053,7 @@ else tokIt[1].text = tokIt[1].text[3..$]; } } - else if((tok.text == "GUID" || tok.text == "IID" || tok.text == "CLSID") && + else if((tok.text == "GUID" || tok.text == "IID" || tok.text == "CLSID") && tokIt[1].type == Token.Identifier && tokIt[2].text == "=" && tokIt[3].text == "{") { convertGUID(tokIt + 4); @@ -2143,7 +2134,7 @@ else case "__stdcall": return "/*__stdcall*/"; case "__cdecl": return "/*__cdecl*/"; case "__gdi_entry": return "/*__gdi_entry*/"; - + //case "const": return "/*const*/"; case "inline": return "/*inline*/"; case "__int64": return "long"; @@ -2161,7 +2152,7 @@ else case "__in_opt": case "__in_z_opt": case "__in_bound": - + case "__allocator": case "__out": case "__out_opt": @@ -2177,7 +2168,7 @@ else case "__deref_opt_out": case "__deref_opt_out_opt": case "__deref_opt_inout_opt": - + case "__callback": case "__format_string": case "__reserved": @@ -2185,12 +2176,12 @@ else case "__nullterminated": case "__nullnullterminated": case "__possibly_notnullterminated": - + case "__drv_interlocked": case "__drv_sameIRQL": case "__drv_inTry": case "__drv_aliasesMem": - + case "__post": case "__notvalid": case "__analysis_noreturn": @@ -2262,7 +2253,7 @@ else string base = baseName(file); if(excludefiles.contains(base)) return; - + if(!srcfiles.contains(file)) srcfiles ~= file; } @@ -2286,7 +2277,7 @@ else { if (indexOf(file, '*') >= 0 || indexOf(file, '?') >= 0) addSourceByPattern("+" ~ file); - else + else { if(!exists(file)) file = dirName(file) ~ "\\shared\\" ~ baseName(file); @@ -2384,7 +2375,7 @@ version(remove_pp) {} else foreach (string name; dirEntries(portdir, SpanMode.shallow)) if (globMatch(baseName(name), "*.d")) ins ~= " \n"; - + string folder = "port"; string[] files = split(sources); @@ -2410,7 +2401,7 @@ version(remove_pp) {} else void setCurrentFile(string file) { currentFile = file; - + currentFullModule = fixImport(file); auto p = lastIndexOf(currentFullModule, '.'); if(p >= 0) @@ -2443,7 +2434,7 @@ version(remove_pp) {} else return -1; } - getopt(argv, + getopt(argv, "vsi", &vsi_base_path, "dte", &dte_path, "win", &win_path, @@ -2470,7 +2461,7 @@ version(remove_pp) {} else } initFiles(); - + // GC.disable(); disabled_defines["__VARIANT_NAME_1"] = 1; @@ -2480,7 +2471,7 @@ version(remove_pp) {} else disabled_defines["uuid_constant"] = 1; // declared twice - disabled_defines["VBProjectProperties2"] = 1; + disabled_defines["VBProjectProperties2"] = 1; disabled_defines["VBProjectConfigProperties2"] = 1; // declared twice disabled_defines["IID_ProjectProperties2"] = 1; disabled_defines["IID_ProjectConfigurationProperties2"] = 1; @@ -2492,7 +2483,7 @@ version(remove_pp) {} else disabled_defines["SELCONTAINER_DONTPROPAGATE"] = 1; disabled_defines["ME_UNKNOWN_MENU_ITEM"] = 1; disabled_defines["ME_FIRST_MENU_ITEM"] = 1; - + // win sdk disabled_defines["pascal"] = 1; disabled_defines["WINBASEAPI"] = 1; @@ -2508,7 +2499,7 @@ version(remove_pp) {} else // commctrl.h disabled_defines["HDM_TRANSLATEACCELERATOR"] = 1; - + foreach(string file; argv[1..$]) addSources(file); @@ -2569,7 +2560,7 @@ version(remove_pp) {} else sources ~= "\n"; if(!sdk_d_path.empty) { - version(vsi) + version(vsi) string srcfile = sdk_d_path ~ "\\vsi_sources"; else string srcfile = sdk_d_path ~ "\\sources"; @@ -2651,7 +2642,7 @@ alias tagELEMDESC ELEMDESC; alias tagELEMDESC * LPELEMDESC; unittest { string txt = q{ - int x; +int x; cpp_quote("#ifndef WIN16") typedef struct tagSIZE { @@ -2669,18 +2660,18 @@ cpp_quote("#endif // WIN16") version(remove_pp) string exptxt = q{ - int x; +int x; struct tagSIZE { LONG cx; LONG cy; } -alias tagSIZE SIZE; alias tagSIZE *PSIZE; alias tagSIZE *LPSIZE; +alias tagSIZE SIZE; alias tagSIZE *PSIZE; alias tagSIZE *LPSIZE; }q{ // WIN16 }; else // !remove_pp string exptxt = q{ - int x; +int x; version(all) /* #ifndef WIN16 */ { struct tagSIZE { @@ -2736,7 +2727,7 @@ unittest hallo2 "; string exptxt = " -int convert() { return +int convert() { return " " hello; } // #define noconvert(n,m) \\ // hallo1 |\\ @@ -2835,7 +2826,7 @@ alias _PROPSHEETPAGEA_V2 _PROPSHEETPAGEA; } else { alias _PROPSHEETPAGEA_V1 _PROPSHEETPAGEA; -} +} " " "; testConvert(txt, exptxt, "prsht"); diff --git a/doc/Coverage.dd b/doc/Coverage.dd index 76ca3064..803b6e08 100644 --- a/doc/Coverage.dd +++ b/doc/Coverage.dd @@ -1,50 +1,50 @@ -Ddoc - -$(P DMD comes with an option to instrument an executable for coverage analysis -during its execution. You can enable it on the project configuration page "Code Generation".) - -$(IMG_CENTER images/prop_codegen.png) - -$(P With code coverage enabled the executable will record -the source code lines that have been executed and will mark the lines that have -code generated but are never executed. This information is written into files named as the -source files but with extension ".lst".) - -
-$(P If you enable option "Colorize Coverage" in -the Visual D colorizer settings (reachable through the "Open Language Options..." entry -in the Visual D menu), these lines will be highlighted in the editor. The highlighting will not show -up unless the lst-file is newer than the source file as it will probably be out of sync -otherwise. -) - - -$(IMG_CENTER images/coverage_forever.png) -
- -$(P If you start editing the source file Visual D will try to keep coverage information in sync. -If you want to get rid of the coverage coloring, just resave the source file. -Visual D will assume the coverage is invalid then and stop displaying it. -) - -
-$(P Enabling "Show coverage margin" on the same options page will add a column -to the editor window that displays the exact coverage counters for each line.) - -$(P The very first line contains the percentage of covered source lines with generated -code in the module.) - -$(P [Visual Studio 2008 displays the coverage margin as an overlay on the right side -of the editor window.]) - - -$(IMG_CENTER images/coveragemargin_forever.png) -
- -This option can be combined with the "Compile and Run" command to easily test -the code coverage of unittests within a module. See $(LINK2 News36.html, Unit testing and code coverage) -for an example. - -Macros: - TITLE=Code Coverage - +Ddoc + +$(P DMD comes with an option to instrument an executable for coverage analysis +during its execution. You can enable it on the project configuration page "Code Generation".) + +$(IMG_CENTER images/prop_codegen.png) + +$(P With code coverage enabled the executable will record +the source code lines that have been executed and will mark the lines that have +code generated but are never executed. This information is written into files named as the +source files but with extension ".lst".) + +
+$(P If you enable option "Colorize Coverage" in +the Visual D colorizer settings (reachable through the "Open Language Options..." entry +in the Visual D menu), these lines will be highlighted in the editor. The highlighting will not show +up unless the lst-file is newer than the source file as it will probably be out of sync +otherwise. +) + + +$(IMG_CENTER images/coverage_forever.png) +
+ +$(P If you start editing the source file Visual D will try to keep coverage information in sync. +If you want to get rid of the coverage coloring, just resave the source file. +Visual D will assume the coverage is invalid then and stop displaying it. +) + +
+$(P Enabling "Show coverage margin" on the same options page will add a column +to the editor window that displays the exact coverage counters for each line.) + +$(P The very first line contains the percentage of covered source lines with generated +code in the module.) + +$(P [Visual Studio 2008 displays the coverage margin as an overlay on the right side +of the editor window.]) + + +$(IMG_CENTER images/coveragemargin_forever.png) +
+ +This option can be combined with the "Compile and Run" command to easily test +the code coverage of unittests within a module. See $(LINK2 News36.html, Unit testing and code coverage) +for an example. + +Macros: + TITLE=Code Coverage + diff --git a/doc/VersionHistory.dd b/doc/VersionHistory.dd index ff7a3a29..a10795e7 100644 --- a/doc/VersionHistory.dd +++ b/doc/VersionHistory.dd @@ -1,6 +1,6 @@ Ddoc -$(H2 2015-5-16 Version 0.3.41) +$(H2 2015-8-5 Version 0.3.42) $(UL $(LI build system $(UL diff --git a/nsis/visuald.nsi b/nsis/visuald.nsi index 1b952a39..f245011e 100644 --- a/nsis/visuald.nsi +++ b/nsis/visuald.nsi @@ -12,6 +12,9 @@ ; define DPARSER to include DParser COM server installation (expected at ../bin/Release/DParserCOMServer) !define DPARSER +; define VDSERVER to include vdserver COM server installation +; !define VDSERVER + ; define VDEXTENSIONS to include C# extensions (expected at ../bin/Release/vdextensions) !define VDEXTENSIONS @@ -185,7 +188,7 @@ Section "Visual Studio package" SecPackage ${SetOutPath} "$INSTDIR" ${File} ..\bin\${CONFIG}\ ${DLLNAME} - ${File} ..\bin\${CONFIG}\ vdserver.exe + ${File} ..\bin\${CONFIG}\ vdserver.tlb ${File} ..\bin\${CONFIG}\ pipedmd.exe ${File} ..\bin\${CONFIG}\ filemonitor.dll ${File} ..\bin\${CONFIG}\ dcxxfilt.exe @@ -193,10 +196,21 @@ Section "Visual Studio package" SecPackage ${File} ..\ LICENSE_1_0.txt ${File} ..\ CHANGES +!ifdef VDSERVER + ${File} ..\bin\${CONFIG}\ vdserver.exe +!endif + !ifdef VDEXTENSIONS ${File} ..\bin\${CONFIG}\vdextensions\ vdextensions.dll !endif +!ifdef DPARSER + ${SetOutPath} "$INSTDIR\DParser" + ${File} ..\bin\Release\DParserCOMServer\ DParserCOMServer.exe + ${File} ..\bin\Release\DParserCOMServer\ D_Parser.dll +!endif + + ${SetOutPath} "$INSTDIR\Templates" ${SetOutPath} "$INSTDIR\Templates\Items" ${File} ..\visuald\Templates\Items\ empty.d @@ -241,7 +255,14 @@ Section "Visual Studio package" SecPackage ${SetOutPath} "$INSTDIR\Templates\CodeSnippets\Snippets" ${File} ..\visuald\Templates\CodeSnippets\Snippets\ *.snippet + Call RegisterIVDServer +!ifdef VDSERVER Call RegisterVDServer +!endif + +!ifdef DPARSER + Call RegisterDParser +!endif ;Store installation folder WriteRegStr HKCU "Software\${APPNAME}" "" $INSTDIR @@ -493,19 +514,6 @@ ${MementoSection} "mago" SecMago ${MementoSectionEnd} !endif -!ifdef DPARSER -;-------------------------------- -${MementoSection} "DParser" SecDParser - - ${SetOutPath} "$INSTDIR\DParser" - ${File} ..\bin\Release\DParserCOMServer\ DParserCOMServer.exe - ${File} ..\bin\Release\DParserCOMServer\ D_Parser.dll - - Call RegisterDParser - -${MementoSectionEnd} -!endif - ${MementoSectionDone} Section -closelogfile @@ -539,10 +547,6 @@ SectionEnd LangString DESC_SecMago ${LANG_ENGLISH} "Mago is a debug engine especially designed for the D-Language." LangString DESC_SecMago2 ${LANG_ENGLISH} "$\r$\nMago is written by Aldo Nunez. Distributed under the Apache License Version 2.0. See www.dsource.org/ projects/mago_debugger" !endif -!ifdef DPARSER - LangString DESC_SecDParser ${LANG_ENGLISH} "DParser is a Parser && Resolver && Completion library for D." - LangString DESC_SecDParser2 ${LANG_ENGLISH} "$\r$\nDParser is written by Alexander Bothe. Distributed under the Apache License Version 2.0. See https://github.com/ aBothe/D_Parser" -!endif ;Assign language strings to sections !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN @@ -565,9 +569,6 @@ SectionEnd !endif !ifdef MAGO !insertmacro MUI_DESCRIPTION_TEXT ${SecMago} $(DESC_SecMago)$(DESC_SecMago2) -!endif -!ifdef DPARSER - !insertmacro MUI_DESCRIPTION_TEXT ${SecDParser} $(DESC_SecDParser)$(DESC_SecDParser2) !endif !insertmacro MUI_FUNCTION_DESCRIPTION_END @@ -688,6 +689,7 @@ Section "Uninstall" DeleteRegKey ${VS_REGISTRY_ROOT} "${VS2015_REGISTRY_KEY}\InstalledProducts\Mago" !endif + Call un.RegisterIVDServer Call un.RegisterVDServer Call un.RegisterDParser @@ -980,15 +982,27 @@ FunctionEnd !define VDSERVER_INTERFACE_NAME IVDServer !define VDSERVER_INTERFACE_CLSID {002a2de9-8bb6-484d-9901-7e4ad4084715} +Function RegisterIVDServer + + WriteRegStr ${VDSERVER_REG_ROOT} "TypeLib\${VDSERVER_TYPELIB_CLSID}\1.0\0\win32" "" $INSTDIR\vdserver.tlb + WriteRegStr ${VDSERVER_REG_ROOT} "Interface\${VDSERVER_INTERFACE_CLSID}" "" ${VDSERVER_INTERFACE_NAME} + WriteRegStr ${VDSERVER_REG_ROOT} "Interface\${VDSERVER_INTERFACE_CLSID}\ProxyStubClsid32" "" {00020424-0000-0000-C000-000000000046} + WriteRegStr ${VDSERVER_REG_ROOT} "Interface\${VDSERVER_INTERFACE_CLSID}\TypeLib" "" ${VDSERVER_TYPELIB_CLSID} + +FunctionEnd + +Function un.RegisterIVDServer + + DeleteRegKey ${VDSERVER_REG_ROOT} "TypeLib\${VDSERVER_TYPELIB_CLSID}" + DeleteRegKey ${VDSERVER_REG_ROOT} "Interface\${VDSERVER_INTERFACE_CLSID}" + +FunctionEnd + Function RegisterVDServer WriteRegStr ${VDSERVER_REG_ROOT} "${VDSERVER_FACTORY_NAME}\CLSID" "" ${VDSERVER_FACTORY_CLSID} WriteRegStr ${VDSERVER_REG_ROOT} "CLSID\${VDSERVER_FACTORY_CLSID}\LocalServer32" "" $INSTDIR\vdserver.exe WriteRegStr ${VDSERVER_REG_ROOT} "CLSID\${VDSERVER_FACTORY_CLSID}\TypeLib" "" ${VDSERVER_TYPELIB_CLSID} - WriteRegStr ${VDSERVER_REG_ROOT} "TypeLib\${VDSERVER_TYPELIB_CLSID}\1.0\0\win32" "" $INSTDIR\vdserver.exe - WriteRegStr ${VDSERVER_REG_ROOT} "Interface\${VDSERVER_INTERFACE_CLSID}" "" ${VDSERVER_INTERFACE_NAME} - WriteRegStr ${VDSERVER_REG_ROOT} "Interface\${VDSERVER_INTERFACE_CLSID}\ProxyStubClsid32" "" {00020424-0000-0000-C000-000000000046} - WriteRegStr ${VDSERVER_REG_ROOT} "Interface\${VDSERVER_INTERFACE_CLSID}\TypeLib" "" ${VDSERVER_TYPELIB_CLSID} FunctionEnd @@ -996,8 +1010,6 @@ Function un.RegisterVDServer DeleteRegKey ${VDSERVER_REG_ROOT} "${VDSERVER_FACTORY_NAME}" DeleteRegKey ${VDSERVER_REG_ROOT} "CLSID\${VDSERVER_FACTORY_CLSID}" - DeleteRegKey ${VDSERVER_REG_ROOT} "TypeLib\${VDSERVER_TYPELIB_CLSID}" - DeleteRegKey ${VDSERVER_REG_ROOT} "Interface\${VDSERVER_INTERFACE_CLSID}" FunctionEnd diff --git a/sdk/port/sharedvenusids.d b/sdk/port/sharedvenusids.d index 5d504dae..7b4c6af2 100644 --- a/sdk/port/sharedvenusids.d +++ b/sdk/port/sharedvenusids.d @@ -1,3 +1,3 @@ -// missing from VS12 SDK? - -module sdk.port.sharedvenusids; +// missing from VS12 SDK? + +module sdk.port.sharedvenusids; diff --git a/stdext/httpget.d b/stdext/httpget.d index 43208e0c..bd39a071 100644 --- a/stdext/httpget.d +++ b/stdext/httpget.d @@ -8,8 +8,8 @@ module stdext.httpget; -import std.string, std.conv, std.stream, std.stdio; -import std.socket, std.socketstream; +import std.string, std.conv, std.stdio; +import std.socket; import std.algorithm : min; ulong httpget(string url, string dstfile, ulong partial_start = 0, ulong partial_length = ulong.max) @@ -60,7 +60,7 @@ ulong httpget(string domain, ushort port, string url, string dstfile, ulong part Socket sock = new TcpSocket(new InternetAddress(domain, port)); scope(exit) sock.close(); - Stream ss = new SocketStream(sock); + SocketStream ss = new SocketStream(sock); debug (HTMLGET) writefln("Connected! Requesting URL \"%s\"...", url); @@ -90,7 +90,7 @@ ulong httpget(string domain, ushort port, string url, string dstfile, ulong part writeln(line); } - auto file = new std.stream.File(dstfile, FileMode.OutNew); + auto file = new std.stdio.File(dstfile, "w"); scope(exit) file.close(); auto bufSize = min(partial_length + 1, 65536); @@ -102,9 +102,138 @@ ulong httpget(string domain, ushort port, string url, string dstfile, ulong part while ((read = ss.readBlock(buf.ptr, bufSize)) > 0) { int skip = (testLF && buf[0] == '\n' ? 1 : 0); - file.writeBlock(buf.ptr + skip, read - skip); + file.rawWrite(buf[skip..read]); testLF = false; sumRead += read - skip; } return sumRead; } + +// deprecated in phobos 2.069, so extract what's needed +class SocketStream +{ + private Socket sock; + + this(Socket s) + { + sock = s; + } + + /** + * Attempts to read the entire block, waiting if necessary. + */ + size_t readBlock(void* _buffer, size_t size) + { + if (size == 0) + return size; + + ubyte* buffer = cast(ubyte*)_buffer; + auto len = sock.receive(buffer[0 .. size]); + //readEOF = cast(bool)(len == 0); + if (len == sock.ERROR) + len = 0; + return len; + } + + // reads a line, terminated by either CR, LF, CR/LF, or EOF + char[] readLine() + { + return readLine(null); + } + + // reads a line, terminated by either CR, LF, CR/LF, or EOF + // reusing the memory in buffer if result will fit and otherwise + // allocates a new string + char[] readLine(char[] result) + { + size_t strlen = 0; + char ch = getc(); + while (true) { + switch (ch) { + case '\r': + prevCr = true; + goto case; + case '\n': + case char.init: + result.length = strlen; + return result; + + default: + if (strlen < result.length) { + result[strlen] = ch; + } else { + result ~= ch; + } + strlen++; + } + ch = getc(); + } + result.length = strlen; + return result; + } + + // unget buffer + private wchar[] unget; + final bool ungetAvailable() { return unget.length > 1; } + private bool prevCr = false; + + // reads and returns next character from the stream, + // handles characters pushed back by ungetc() + // returns char.init on eof. + char getc() + { + char c; + if (prevCr) { + prevCr = false; + c = getc(); + if (c != '\n') + return c; + } + if (unget.length > 1) { + c = cast(char)unget[unget.length - 1]; + unget.length = unget.length - 1; + } else { + readBlock(&c,1); + } + return c; + } + + + /** + * Attempts to write the entire block, waiting if necessary. + */ + size_t writeBlock(const void* _buffer, size_t size) + { + if (size == 0) + return size; + + ubyte* buffer = cast(ubyte*)_buffer; + auto len = sock.send(buffer[0 .. size]); + //readEOF = cast(bool)(len == 0); + if (len == sock.ERROR) + len = 0; + return len; + } + + // writes block of data of specified size, + // throws WriteException on error + void writeExact(const void* buffer, size_t size) + { + const(void)* p = buffer; + for(;;) { + if (!size) return; + size_t writesize = writeBlock(p, size); + if (writesize == 0) break; + p += writesize; + size -= writesize; + } + if (size != 0) + throw new Exception("unable to write to stream"); + } + + // writes a string, throws WriteException on error + void writeString(const(char)[] s) + { + writeExact(s.ptr, s.length); + } +} diff --git a/tools/pipedmd.d b/tools/pipedmd.d index fe1fcae3..67db25b0 100644 --- a/tools/pipedmd.d +++ b/tools/pipedmd.d @@ -2,7 +2,7 @@ // Written and provided by Benjamin Thaut // Complications improved by Rainer Schuetze // -// file access monitoring added by Rainer Schuetze, needs filemonitor.dll in the same +// file access monitoring added by Rainer Schuetze, needs filemonitor.dll in the same // directory as pipedmd.exe module pipedmd; @@ -25,7 +25,7 @@ alias core.stdc.stdio.stdout stdout; static bool isIdentifierChar(char ch) { - // include C++,Pascal,Windows mangling and UTF8 encoding and compression + // include C++,Pascal,Windows mangling and UTF8 encoding and compression return ch >= 0x80 || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'; } @@ -49,7 +49,7 @@ int main(string[] argv) printf("pipedmd V0.2, written 2012 by Benjamin Thaut, complications improved by Rainer Schuetze\n"); printf("decompresses and demangles names in OPTLINK and ld messages\n"); printf("\n"); - printf("usage: %.*s [-nodemangle] [-gdcmode | -msmode] [-deps depfile] [executable] [arguments]\n", + printf("usage: %.*s [-nodemangle] [-gdcmode | -msmode] [-deps depfile] [executable] [arguments]\n", argv[0].length, argv[0].ptr); return -1; } @@ -57,7 +57,7 @@ int main(string[] argv) string depsfile; bool doDemangle = true; bool demangleAll = false; //not just linker messages - bool gdcMode = false; //gcc linker + bool gdcMode = false; //gcc linker bool msMode = false; //microsoft linker bool verbose = false; @@ -121,7 +121,7 @@ int main(string[] argv) string trackfilewr = stripExtension(baseName(exe)) ~ ".write.*.tlog"; foreach(f; std.file.dirEntries(trackdir, std.file.SpanMode.shallow)) if (globMatch(baseName(f), trackfile) || globMatch(baseName(f), trackfilewr)) - std.file.remove(f); + std.file.remove(f.name); command ~= " /c"; } else if (isX64) @@ -150,7 +150,7 @@ int main(string[] argv) foreach(f; std.file.dirEntries(trackdir, std.file.SpanMode.shallow)) if (globMatch(baseName(f), trackfile)) { - ubyte[] fbuf = cast(ubyte[])std.file.read(f); + ubyte[] fbuf = cast(ubyte[])std.file.read(f.name); // strip BOM from all but the first file if (buf.length && fbuf.length > 1 && fbuf[0] == 0xFF && fbuf[1] == 0xFE) fbuf = fbuf[2..$]; @@ -159,7 +159,7 @@ int main(string[] argv) std.file.write(depsfile, buf); } - + return exitCode; } @@ -170,17 +170,17 @@ int runProcess(string command, string depsfile, bool doDemangle, bool demangleAl HANDLE hStdInRead; HANDLE hStdInWrite; - SECURITY_ATTRIBUTES saAttr; + SECURITY_ATTRIBUTES saAttr; - // Set the bInheritHandle flag so pipe handles are inherited. + // Set the bInheritHandle flag so pipe handles are inherited. saAttr.nLength = SECURITY_ATTRIBUTES.sizeof; - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = null; + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = null; - // Create a pipe for the child process's STDOUT. + // Create a pipe for the child process's STDOUT. - if ( ! CreatePipe(&hStdOutRead, &hStdOutWrite, &saAttr, 0) ) + if ( ! CreatePipe(&hStdOutRead, &hStdOutWrite, &saAttr, 0) ) assert(0); // Ensure the read handle to the pipe for STDOUT is not inherited. @@ -194,19 +194,19 @@ int runProcess(string command, string depsfile, bool doDemangle, bool demangleAl if ( ! SetHandleInformation(hStdInWrite, HANDLE_FLAG_INHERIT, 0) ) assert(0); - PROCESS_INFORMATION piProcInfo; + PROCESS_INFORMATION piProcInfo; STARTUPINFOA siStartInfo; - BOOL bSuccess = FALSE; + BOOL bSuccess = FALSE; - // Set up members of the PROCESS_INFORMATION structure. + // Set up members of the PROCESS_INFORMATION structure. memset( &piProcInfo, 0, PROCESS_INFORMATION.sizeof ); - // Set up members of the STARTUPINFO structure. + // Set up members of the STARTUPINFO structure. // This structure specifies the STDIN and STDOUT handles for redirection. memset( &siStartInfo, 0, STARTUPINFOA.sizeof ); - siStartInfo.cb = STARTUPINFOA.sizeof; + siStartInfo.cb = STARTUPINFOA.sizeof; siStartInfo.hStdError = hStdOutWrite; siStartInfo.hStdOutput = hStdOutWrite; siStartInfo.hStdInput = hStdInRead; @@ -214,16 +214,16 @@ int runProcess(string command, string depsfile, bool doDemangle, bool demangleAl int cp = GetKBCodePage(); auto szCommand = toMBSz(command, cp); - bSuccess = CreateProcessA(null, - cast(char*)szCommand, // command line - null, // process security attributes - null, // primary thread security attributes - TRUE, // handles are inherited - CREATE_SUSPENDED, // creation flags - null, // use parent's environment - null, // use parent's current directory - &siStartInfo, // STARTUPINFO pointer - &piProcInfo); // receives PROCESS_INFORMATION + bSuccess = CreateProcessA(null, + cast(char*)szCommand, // command line + null, // process security attributes + null, // primary thread security attributes + TRUE, // handles are inherited + CREATE_SUSPENDED, // creation flags + null, // use parent's environment + null, // use parent's current directory + &siStartInfo, // STARTUPINFO pointer + &piProcInfo); // receives PROCESS_INFORMATION if(!bSuccess) { @@ -604,7 +604,7 @@ void InjectDLL(HANDLE hProcess, string depsfile) } string modpath = to!string(wmodname); string dll = buildPath(std.path.dirName(modpath), "filemonitor.dll"); - + auto wdll = to!wstring(dll) ~ cast(wchar)0; // detect offset of dumpFile HMODULE fmod = LoadLibraryW(wdll.ptr); @@ -738,7 +738,7 @@ extern(C) enum IMAGE_FILE_MACHINE_IA64 = 0x0200; // Intel 64 enum IMAGE_FILE_MACHINE_AMD64 = 0x8664; // AMD64 (K8) - struct IMAGE_FILE_HEADER + struct IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; diff --git a/vdc/abothe/comserver/COMHelper.cs b/vdc/abothe/comserver/COMHelper.cs index 52edb351..431b7887 100644 --- a/vdc/abothe/comserver/COMHelper.cs +++ b/vdc/abothe/comserver/COMHelper.cs @@ -1,281 +1,281 @@ -/****************************** Module Header ******************************\ -* Module Name: COMHelper.cs -* Project: CSExeCOMServer -* Copyright (c) Microsoft Corporation. -* -* COMHelper provides the helper functions to register/unregister COM server -* and encapsulates the native COM APIs to be used in .NET. -* -* This source is subject to the Microsoft Public License. -* See http://www.microsoft.com/en-us/openness/licenses.aspx#MPL. -* All other rights reserved. -* -* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, -* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. -\***************************************************************************/ - -#region Using directives -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using Microsoft.Win32; -using System.Reflection; -#endregion - - -internal class COMHelper -{ - /// - /// Register the component as a local server. - /// - /// - public static void RegasmRegisterLocalServer(Type t) - { - GuardNullType(t, "t"); // Check the argument - - // Open the CLSID key of the component. - using (RegistryKey keyCLSID = Registry.ClassesRoot.OpenSubKey( - @"CLSID\" + t.GUID.ToString("B"), /*writable*/true)) - { - // Remove the auto-generated InprocServer32 key after registration - // (REGASM puts it there but we are going out-of-proc). - keyCLSID.DeleteSubKeyTree("InprocServer32"); - - // Create "LocalServer32" under the CLSID key - using (RegistryKey subkey = keyCLSID.CreateSubKey("LocalServer32")) - { - subkey.SetValue("", Assembly.GetExecutingAssembly().Location, - RegistryValueKind.String); - } - } - } - - /// - /// Unregister the component. - /// - /// - public static void RegasmUnregisterLocalServer(Type t) - { - GuardNullType(t, "t"); // Check the argument - - // Delete the CLSID key of the component - Registry.ClassesRoot.DeleteSubKeyTree(@"CLSID\" + t.GUID.ToString("B")); - } - - private static void GuardNullType(Type t, String param) - { - if (t == null) - { - throw new ArgumentException("The CLR type must be specified.", param); - } - } -} - -internal class COMNative -{ - /// - /// CoInitializeEx() can be used to set the apartment model of individual - /// threads. - /// - /// Must be NULL - /// - /// The concurrency model and initialization options for the thread - /// - /// - [DllImport("ole32.dll")] - public static extern int CoInitializeEx(IntPtr pvReserved, uint dwCoInit); - - /// - /// CoUninitialize() is used to uninitialize a COM thread. - /// - [DllImport("ole32.dll")] - public static extern void CoUninitialize(); - - /// - /// Registers an EXE class object with OLE so other applications can - /// connect to it. EXE object applications should call - /// CoRegisterClassObject on startup. It can also be used to register - /// internal objects for use by the same EXE or other code (such as DLLs) - /// that the EXE uses. - /// - /// CLSID to be registered - /// - /// Pointer to the IUnknown interface on the class object whose - /// availability is being published. - /// - /// - /// Context in which the executable code is to be run. - /// - /// - /// How connections are made to the class object. - /// - /// - /// Pointer to a value that identifies the class object registered; - /// - /// - /// - /// PInvoking CoRegisterClassObject to register COM objects is not - /// supported. - /// - [DllImport("ole32.dll")] - public static extern int CoRegisterClassObject( - ref Guid rclsid, - [MarshalAs(UnmanagedType.Interface)] IClassFactory pUnk, - CLSCTX dwClsContext, - REGCLS flags, - out uint lpdwRegister); - - /// - /// Informs OLE that a class object, previously registered with the - /// CoRegisterClassObject function, is no longer available for use. - /// - /// - /// Token previously returned from the CoRegisterClassObject function - /// - /// - [DllImport("ole32.dll")] - public static extern UInt32 CoRevokeClassObject(uint dwRegister); - - /// - /// Called by a server that can register multiple class objects to inform - /// the SCM about all registered classes, and permits activation requests - /// for those class objects. - /// - /// - /// - /// Servers that can register multiple class objects call - /// CoResumeClassObjects once, after having first called - /// CoRegisterClassObject, specifying REGCLS_LOCAL_SERVER | - /// REGCLS_SUSPENDED for each CLSID the server supports. This function - /// causes OLE to inform the SCM about all the registered classes, and - /// begins letting activation requests into the server process. - /// - /// This reduces the overall registration time, and thus the server - /// application startup time, by making a single call to the SCM, no - /// matter how many CLSIDs are registered for the server. Another - /// advantage is that if the server has multiple apartments with - /// different CLSIDs registered in different apartments, or is a free- - /// threaded server, no activation requests will come in until the server - /// calls CoResumeClassObjects. This gives the server a chance to - /// register all of its CLSIDs and get properly set up before having to - /// deal with activation requests, and possibly shutdown requests. - /// - [DllImport("ole32.dll")] - public static extern int CoResumeClassObjects(); - - /// - /// Interface Id of IClassFactory - /// - public const string IID_IClassFactory = - "00000001-0000-0000-C000-000000000046"; - - /// - /// Interface Id of IUnknown - /// - public const string IID_IUnknown = - "00000000-0000-0000-C000-000000000046"; - - /// - /// Interface Id of IDispatch - /// - public const string IID_IDispatch = - "00020400-0000-0000-C000-000000000046"; - - /// - /// Class does not support aggregation (or class object is remote) - /// - public const int CLASS_E_NOAGGREGATION = unchecked((int)0x80040110); - - /// - /// No such interface supported - /// - public const int E_NOINTERFACE = unchecked((int)0x80004002); -} - -/// -/// You must implement this interface for every class that you register in -/// the system registry and to which you assign a CLSID, so objects of that -/// class can be created. -/// http://msdn.microsoft.com/en-us/library/ms694364.aspx -/// -[ComImport(), ComVisible(false), -InterfaceType(ComInterfaceType.InterfaceIsIUnknown), -Guid(COMNative.IID_IClassFactory)] -internal interface IClassFactory -{ - /// - /// Creates an uninitialized object. - /// - /// - /// - /// Reference to the identifier of the interface to be used to - /// communicate with the newly created object. If pUnkOuter is NULL, this - /// parameter is frequently the IID of the initializing interface. - /// - /// - /// Address of pointer variable that receives the interface pointer - /// requested in riid. - /// - /// S_OK means success. - [PreserveSig] - int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject); - - /// - /// Locks object application open in memory. - /// - /// - /// If TRUE, increments the lock count; - /// if FALSE, decrements the lock count. - /// - /// S_OK means success. - [PreserveSig] - int LockServer(bool fLock); -} - -/// -/// Values from the CLSCTX enumeration are used in activation calls to -/// indicate the execution contexts in which an object is to be run. These -/// values are also used in calls to CoRegisterClassObject to indicate the -/// set of execution contexts in which a class object is to be made available -/// for requests to construct instances. -/// -[Flags] -internal enum CLSCTX : uint -{ - INPROC_SERVER = 0x1, - INPROC_HANDLER = 0x2, - LOCAL_SERVER = 0x4, - INPROC_SERVER16 = 0x8, - REMOTE_SERVER = 0x10, - INPROC_HANDLER16 = 0x20, - RESERVED1 = 0x40, - RESERVED2 = 0x80, - RESERVED3 = 0x100, - RESERVED4 = 0x200, - NO_CODE_DOWNLOAD = 0x400, - RESERVED5 = 0x800, - NO_CUSTOM_MARSHAL = 0x1000, - ENABLE_CODE_DOWNLOAD = 0x2000, - NO_FAILURE_LOG = 0x4000, - DISABLE_AAA = 0x8000, - ENABLE_AAA = 0x10000, - FROM_DEFAULT_CONTEXT = 0x20000, - ACTIVATE_32_BIT_SERVER = 0x40000, - ACTIVATE_64_BIT_SERVER = 0x80000 -} - -/// -/// The REGCLS enumeration defines values used in CoRegisterClassObject to -/// control the type of connections to a class object. -/// -[Flags] -internal enum REGCLS : uint -{ - SINGLEUSE = 0, - MULTIPLEUSE = 1, - MULTI_SEPARATE = 2, - SUSPENDED = 4, - SURROGATE = 8, +/****************************** Module Header ******************************\ +* Module Name: COMHelper.cs +* Project: CSExeCOMServer +* Copyright (c) Microsoft Corporation. +* +* COMHelper provides the helper functions to register/unregister COM server +* and encapsulates the native COM APIs to be used in .NET. +* +* This source is subject to the Microsoft Public License. +* See http://www.microsoft.com/en-us/openness/licenses.aspx#MPL. +* All other rights reserved. +* +* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +\***************************************************************************/ + +#region Using directives +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using Microsoft.Win32; +using System.Reflection; +#endregion + + +internal class COMHelper +{ + /// + /// Register the component as a local server. + /// + /// + public static void RegasmRegisterLocalServer(Type t) + { + GuardNullType(t, "t"); // Check the argument + + // Open the CLSID key of the component. + using (RegistryKey keyCLSID = Registry.ClassesRoot.OpenSubKey( + @"CLSID\" + t.GUID.ToString("B"), /*writable*/true)) + { + // Remove the auto-generated InprocServer32 key after registration + // (REGASM puts it there but we are going out-of-proc). + keyCLSID.DeleteSubKeyTree("InprocServer32"); + + // Create "LocalServer32" under the CLSID key + using (RegistryKey subkey = keyCLSID.CreateSubKey("LocalServer32")) + { + subkey.SetValue("", Assembly.GetExecutingAssembly().Location, + RegistryValueKind.String); + } + } + } + + /// + /// Unregister the component. + /// + /// + public static void RegasmUnregisterLocalServer(Type t) + { + GuardNullType(t, "t"); // Check the argument + + // Delete the CLSID key of the component + Registry.ClassesRoot.DeleteSubKeyTree(@"CLSID\" + t.GUID.ToString("B")); + } + + private static void GuardNullType(Type t, String param) + { + if (t == null) + { + throw new ArgumentException("The CLR type must be specified.", param); + } + } +} + +internal class COMNative +{ + /// + /// CoInitializeEx() can be used to set the apartment model of individual + /// threads. + /// + /// Must be NULL + /// + /// The concurrency model and initialization options for the thread + /// + /// + [DllImport("ole32.dll")] + public static extern int CoInitializeEx(IntPtr pvReserved, uint dwCoInit); + + /// + /// CoUninitialize() is used to uninitialize a COM thread. + /// + [DllImport("ole32.dll")] + public static extern void CoUninitialize(); + + /// + /// Registers an EXE class object with OLE so other applications can + /// connect to it. EXE object applications should call + /// CoRegisterClassObject on startup. It can also be used to register + /// internal objects for use by the same EXE or other code (such as DLLs) + /// that the EXE uses. + /// + /// CLSID to be registered + /// + /// Pointer to the IUnknown interface on the class object whose + /// availability is being published. + /// + /// + /// Context in which the executable code is to be run. + /// + /// + /// How connections are made to the class object. + /// + /// + /// Pointer to a value that identifies the class object registered; + /// + /// + /// + /// PInvoking CoRegisterClassObject to register COM objects is not + /// supported. + /// + [DllImport("ole32.dll")] + public static extern int CoRegisterClassObject( + ref Guid rclsid, + [MarshalAs(UnmanagedType.Interface)] IClassFactory pUnk, + CLSCTX dwClsContext, + REGCLS flags, + out uint lpdwRegister); + + /// + /// Informs OLE that a class object, previously registered with the + /// CoRegisterClassObject function, is no longer available for use. + /// + /// + /// Token previously returned from the CoRegisterClassObject function + /// + /// + [DllImport("ole32.dll")] + public static extern UInt32 CoRevokeClassObject(uint dwRegister); + + /// + /// Called by a server that can register multiple class objects to inform + /// the SCM about all registered classes, and permits activation requests + /// for those class objects. + /// + /// + /// + /// Servers that can register multiple class objects call + /// CoResumeClassObjects once, after having first called + /// CoRegisterClassObject, specifying REGCLS_LOCAL_SERVER | + /// REGCLS_SUSPENDED for each CLSID the server supports. This function + /// causes OLE to inform the SCM about all the registered classes, and + /// begins letting activation requests into the server process. + /// + /// This reduces the overall registration time, and thus the server + /// application startup time, by making a single call to the SCM, no + /// matter how many CLSIDs are registered for the server. Another + /// advantage is that if the server has multiple apartments with + /// different CLSIDs registered in different apartments, or is a free- + /// threaded server, no activation requests will come in until the server + /// calls CoResumeClassObjects. This gives the server a chance to + /// register all of its CLSIDs and get properly set up before having to + /// deal with activation requests, and possibly shutdown requests. + /// + [DllImport("ole32.dll")] + public static extern int CoResumeClassObjects(); + + /// + /// Interface Id of IClassFactory + /// + public const string IID_IClassFactory = + "00000001-0000-0000-C000-000000000046"; + + /// + /// Interface Id of IUnknown + /// + public const string IID_IUnknown = + "00000000-0000-0000-C000-000000000046"; + + /// + /// Interface Id of IDispatch + /// + public const string IID_IDispatch = + "00020400-0000-0000-C000-000000000046"; + + /// + /// Class does not support aggregation (or class object is remote) + /// + public const int CLASS_E_NOAGGREGATION = unchecked((int)0x80040110); + + /// + /// No such interface supported + /// + public const int E_NOINTERFACE = unchecked((int)0x80004002); +} + +/// +/// You must implement this interface for every class that you register in +/// the system registry and to which you assign a CLSID, so objects of that +/// class can be created. +/// http://msdn.microsoft.com/en-us/library/ms694364.aspx +/// +[ComImport(), ComVisible(false), +InterfaceType(ComInterfaceType.InterfaceIsIUnknown), +Guid(COMNative.IID_IClassFactory)] +internal interface IClassFactory +{ + /// + /// Creates an uninitialized object. + /// + /// + /// + /// Reference to the identifier of the interface to be used to + /// communicate with the newly created object. If pUnkOuter is NULL, this + /// parameter is frequently the IID of the initializing interface. + /// + /// + /// Address of pointer variable that receives the interface pointer + /// requested in riid. + /// + /// S_OK means success. + [PreserveSig] + int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject); + + /// + /// Locks object application open in memory. + /// + /// + /// If TRUE, increments the lock count; + /// if FALSE, decrements the lock count. + /// + /// S_OK means success. + [PreserveSig] + int LockServer(bool fLock); +} + +/// +/// Values from the CLSCTX enumeration are used in activation calls to +/// indicate the execution contexts in which an object is to be run. These +/// values are also used in calls to CoRegisterClassObject to indicate the +/// set of execution contexts in which a class object is to be made available +/// for requests to construct instances. +/// +[Flags] +internal enum CLSCTX : uint +{ + INPROC_SERVER = 0x1, + INPROC_HANDLER = 0x2, + LOCAL_SERVER = 0x4, + INPROC_SERVER16 = 0x8, + REMOTE_SERVER = 0x10, + INPROC_HANDLER16 = 0x20, + RESERVED1 = 0x40, + RESERVED2 = 0x80, + RESERVED3 = 0x100, + RESERVED4 = 0x200, + NO_CODE_DOWNLOAD = 0x400, + RESERVED5 = 0x800, + NO_CUSTOM_MARSHAL = 0x1000, + ENABLE_CODE_DOWNLOAD = 0x2000, + NO_FAILURE_LOG = 0x4000, + DISABLE_AAA = 0x8000, + ENABLE_AAA = 0x10000, + FROM_DEFAULT_CONTEXT = 0x20000, + ACTIVATE_32_BIT_SERVER = 0x40000, + ACTIVATE_64_BIT_SERVER = 0x80000 +} + +/// +/// The REGCLS enumeration defines values used in CoRegisterClassObject to +/// control the type of connections to a class object. +/// +[Flags] +internal enum REGCLS : uint +{ + SINGLEUSE = 0, + MULTIPLEUSE = 1, + MULTI_SEPARATE = 2, + SUSPENDED = 4, + SURROGATE = 8, } \ No newline at end of file diff --git a/vdc/abothe/comserver/DParserCOMServer.cs b/vdc/abothe/comserver/DParserCOMServer.cs index 4f36d976..946b2dc2 100644 --- a/vdc/abothe/comserver/DParserCOMServer.cs +++ b/vdc/abothe/comserver/DParserCOMServer.cs @@ -1,302 +1,302 @@ -/****************************** Module Header ******************************\ -Module Name: ExeCOMServer.cs -Project: CSExeCOMServer -Copyright (c) Microsoft Corporation. - -ExeCOMServer encapsulates the skeleton of an out-of-process COM server in -C#. The class implements the singleton design pattern and it's thread-safe. -To start the server, call CSExeCOMServer.Instance.Run(). If the server is -running, the function returns directly. Inside the Run method, it registers -the class factories for the COM classes to be exposed from the COM server, -and starts the message loop to wait for the drop of lock count to zero. -When lock count equals zero, it revokes the registrations and quits the -server. - -The lock count of the server is incremented when a COM object is created, -and it's decremented when the object is released (GC-ed). In order that the -COM objects can be GC-ed in time, ExeCOMServer triggers GC every 5 seconds -by running a Timer after the server is started. - -This source is subject to the Microsoft Public License. -See http://www.microsoft.com/en-us/openness/licenses.aspx#MPL. -All other rights reserved. - -THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, -EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. -\***************************************************************************/ - -#region Using directives -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using System.Threading; -#endregion - - -namespace DParserCOMServer -{ - [Guid("002a2de9-8bb6-484d-aa02-7e4ad4084715"), ComVisible(true)] - public class VDServerClassFactory : IClassFactory - { - public int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject) - { - ppvObject = IntPtr.Zero; - - if (pUnkOuter != IntPtr.Zero) - { - // The pUnkOuter parameter was non-NULL and the object does - // not support aggregation. - Marshal.ThrowExceptionForHR(COMNative.CLASS_E_NOAGGREGATION); - } - - if (riid == new Guid(IID.IVDServer) || - riid == new Guid(COMNative.IID_IDispatch) || - riid == new Guid(COMNative.IID_IUnknown)) - { - // Create the instance of the .NET object - ppvObject = Marshal.GetComInterfaceForObject(new VDServer(), typeof(IVDServer)); - } - else - { - // The object that ppvObject points to does not support the - // interface identified by riid. - Marshal.ThrowExceptionForHR(COMNative.E_NOINTERFACE); - } - return 0; // S_OK - } - - public int LockServer(bool fLock) - { - if(fLock) - ExeCOMServer.Instance.Lock(); - else - ExeCOMServer.Instance.Unlock(); - return 0; // S_OK - } - } - - sealed internal class ExeCOMServer - { - #region Singleton Pattern - - private ExeCOMServer() - { - } - - private static ExeCOMServer _instance = new ExeCOMServer(); - public static ExeCOMServer Instance - { - get { return _instance; } - } - - #endregion - - - private object syncRoot = new Object(); // For thread-sync in lock - private bool _bRunning = false; // Whether the server is running - - // The ID of the thread that runs the message loop - private uint _nMainThreadID = 0; - - // The lock count (the number of active COM objects) in the server - private int _nLockCnt = 0; - - // The timer to trigger GC every 5 seconds - private Timer _gcTimer; - - /// - /// The method is call every 5 seconds to GC the managed heap after - /// the COM server is started. - /// - /// - private static void GarbageCollect(object stateInfo) - { - GC.Collect(); // GC - } - - private uint _cookie; - - /// - /// PreMessageLoop is responsible for registering the COM class - /// factories for the COM classes to be exposed from the server, and - /// initializing the key member variables of the COM server (e.g. - /// _nMainThreadID and _nLockCnt). - /// - private void PreMessageLoop() - { - // - // Register the COM class factories. - // - - //Guid clsidSimpleObj = new Guid(SimpleObject.ClassId); - Guid clsid = new Guid(IID.VDServer); - - // Register the SimpleObject class object - int hResult = COMNative.CoRegisterClassObject(ref clsid, new VDServerClassFactory(), - CLSCTX.LOCAL_SERVER, REGCLS.MULTIPLEUSE | REGCLS.SUSPENDED, - out _cookie); - if (hResult != 0) - { - throw new ApplicationException("CoRegisterClassObject failed w/err 0x" + hResult.ToString("X")); - } - - // Inform the SCM about all the registered classes, and begins - // letting activation requests into the server process. - hResult = COMNative.CoResumeClassObjects(); - if (hResult != 0) - { - // Revoke the registration of SimpleObject on failure - if (_cookie != 0) - { - COMNative.CoRevokeClassObject(_cookie); - } - - // Revoke the registration of other classes - // ... - - throw new ApplicationException("CoResumeClassObjects failed w/err 0x" + hResult.ToString("X")); - } - - // Records the ID of the thread that runs the COM server so that - // the server knows where to post the WM_QUIT message to exit the - // message loop. - _nMainThreadID = NativeMethod.GetCurrentThreadId(); - - // Records the count of the active COM objects in the server. - // When _nLockCnt drops to zero, the server can be shut down. - _nLockCnt = 0; - - // Start the GC timer to trigger GC every 5 seconds. - _gcTimer = new Timer(new TimerCallback(GarbageCollect), null, 5000, 5000); - } - - /// - /// RunMessageLoop runs the standard message loop. The message loop - /// quits when it receives the WM_QUIT message. - /// - private void RunMessageLoop() - { - MSG msg; - while (NativeMethod.GetMessage(out msg, IntPtr.Zero, 0, 0)) - { - NativeMethod.TranslateMessage(ref msg); - NativeMethod.DispatchMessage(ref msg); - } - } - - /// - /// PostMessageLoop is called to revoke the registration of the COM - /// classes exposed from the server, and perform the cleanups. - /// - private void PostMessageLoop() - { - // Revoke the registration of COM classes - if (_cookie != 0) - { - COMNative.CoRevokeClassObject(_cookie); - } - - // Dispose the GC timer. - if (_gcTimer != null) - { - _gcTimer.Dispose(); - } - - // Wait for any threads to finish. - Thread.Sleep(1000); - } - - /// - /// Run the COM server. If the server is running, the function - /// returns directly. - /// - /// The method is thread-safe. - public void Run() - { - lock (syncRoot) // Ensure thread-safe - { - // If the server is running, return directly. - if (_bRunning) - return; - - // Indicate that the server is running now. - _bRunning = true; - } - - try - { - // Call PreMessageLoop to initialize the member variables - // and register the class factories. - PreMessageLoop(); - - try - { - // Run the message loop. - RunMessageLoop(); - } - finally - { - // Call PostMessageLoop to revoke the registration. - PostMessageLoop(); - } - } - finally - { - _bRunning = false; - } - } - - /// - /// Increase the lock count - /// - /// The new lock count after the increment - /// The method is thread-safe. - public int Lock() - { - return Interlocked.Increment(ref _nLockCnt); - } - - /// - /// Decrease the lock count. When the lock count drops to zero, post - /// the WM_QUIT message to the message loop in the main thread to - /// shut down the COM server. - /// - /// The new lock count after the increment - public int Unlock() - { - int nRet = Interlocked.Decrement(ref _nLockCnt); - - // If lock drops to zero, attempt to terminate the server. - if (nRet == 0) - { - // Post the WM_QUIT message to the main thread - NativeMethod.PostThreadMessage(_nMainThreadID, NativeMethod.WM_QUIT, UIntPtr.Zero, IntPtr.Zero); - } - - return nRet; - } - - /// - /// Get the current lock count. - /// - /// - public int GetLockCount() - { - return _nLockCnt; - } - } - - class Program - { - /// - /// The main entry point for the application. - /// - static void Main(string[] args) - { - // Run the out-of-process COM server - ExeCOMServer.Instance.Run(); - } - } +/****************************** Module Header ******************************\ +Module Name: ExeCOMServer.cs +Project: CSExeCOMServer +Copyright (c) Microsoft Corporation. + +ExeCOMServer encapsulates the skeleton of an out-of-process COM server in +C#. The class implements the singleton design pattern and it's thread-safe. +To start the server, call CSExeCOMServer.Instance.Run(). If the server is +running, the function returns directly. Inside the Run method, it registers +the class factories for the COM classes to be exposed from the COM server, +and starts the message loop to wait for the drop of lock count to zero. +When lock count equals zero, it revokes the registrations and quits the +server. + +The lock count of the server is incremented when a COM object is created, +and it's decremented when the object is released (GC-ed). In order that the +COM objects can be GC-ed in time, ExeCOMServer triggers GC every 5 seconds +by running a Timer after the server is started. + +This source is subject to the Microsoft Public License. +See http://www.microsoft.com/en-us/openness/licenses.aspx#MPL. +All other rights reserved. + +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +\***************************************************************************/ + +#region Using directives +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using System.Threading; +#endregion + + +namespace DParserCOMServer +{ + [Guid("002a2de9-8bb6-484d-aa02-7e4ad4084715"), ComVisible(true)] + public class VDServerClassFactory : IClassFactory + { + public int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject) + { + ppvObject = IntPtr.Zero; + + if (pUnkOuter != IntPtr.Zero) + { + // The pUnkOuter parameter was non-NULL and the object does + // not support aggregation. + Marshal.ThrowExceptionForHR(COMNative.CLASS_E_NOAGGREGATION); + } + + if (riid == new Guid(IID.IVDServer) || + riid == new Guid(COMNative.IID_IDispatch) || + riid == new Guid(COMNative.IID_IUnknown)) + { + // Create the instance of the .NET object + ppvObject = Marshal.GetComInterfaceForObject(new VDServer(), typeof(IVDServer)); + } + else + { + // The object that ppvObject points to does not support the + // interface identified by riid. + Marshal.ThrowExceptionForHR(COMNative.E_NOINTERFACE); + } + return 0; // S_OK + } + + public int LockServer(bool fLock) + { + if(fLock) + ExeCOMServer.Instance.Lock(); + else + ExeCOMServer.Instance.Unlock(); + return 0; // S_OK + } + } + + sealed internal class ExeCOMServer + { + #region Singleton Pattern + + private ExeCOMServer() + { + } + + private static ExeCOMServer _instance = new ExeCOMServer(); + public static ExeCOMServer Instance + { + get { return _instance; } + } + + #endregion + + + private object syncRoot = new Object(); // For thread-sync in lock + private bool _bRunning = false; // Whether the server is running + + // The ID of the thread that runs the message loop + private uint _nMainThreadID = 0; + + // The lock count (the number of active COM objects) in the server + private int _nLockCnt = 0; + + // The timer to trigger GC every 5 seconds + private Timer _gcTimer; + + /// + /// The method is call every 5 seconds to GC the managed heap after + /// the COM server is started. + /// + /// + private static void GarbageCollect(object stateInfo) + { + GC.Collect(); // GC + } + + private uint _cookie; + + /// + /// PreMessageLoop is responsible for registering the COM class + /// factories for the COM classes to be exposed from the server, and + /// initializing the key member variables of the COM server (e.g. + /// _nMainThreadID and _nLockCnt). + /// + private void PreMessageLoop() + { + // + // Register the COM class factories. + // + + //Guid clsidSimpleObj = new Guid(SimpleObject.ClassId); + Guid clsid = new Guid(IID.VDServer); + + // Register the SimpleObject class object + int hResult = COMNative.CoRegisterClassObject(ref clsid, new VDServerClassFactory(), + CLSCTX.LOCAL_SERVER, REGCLS.MULTIPLEUSE | REGCLS.SUSPENDED, + out _cookie); + if (hResult != 0) + { + throw new ApplicationException("CoRegisterClassObject failed w/err 0x" + hResult.ToString("X")); + } + + // Inform the SCM about all the registered classes, and begins + // letting activation requests into the server process. + hResult = COMNative.CoResumeClassObjects(); + if (hResult != 0) + { + // Revoke the registration of SimpleObject on failure + if (_cookie != 0) + { + COMNative.CoRevokeClassObject(_cookie); + } + + // Revoke the registration of other classes + // ... + + throw new ApplicationException("CoResumeClassObjects failed w/err 0x" + hResult.ToString("X")); + } + + // Records the ID of the thread that runs the COM server so that + // the server knows where to post the WM_QUIT message to exit the + // message loop. + _nMainThreadID = NativeMethod.GetCurrentThreadId(); + + // Records the count of the active COM objects in the server. + // When _nLockCnt drops to zero, the server can be shut down. + _nLockCnt = 0; + + // Start the GC timer to trigger GC every 5 seconds. + _gcTimer = new Timer(new TimerCallback(GarbageCollect), null, 5000, 5000); + } + + /// + /// RunMessageLoop runs the standard message loop. The message loop + /// quits when it receives the WM_QUIT message. + /// + private void RunMessageLoop() + { + MSG msg; + while (NativeMethod.GetMessage(out msg, IntPtr.Zero, 0, 0)) + { + NativeMethod.TranslateMessage(ref msg); + NativeMethod.DispatchMessage(ref msg); + } + } + + /// + /// PostMessageLoop is called to revoke the registration of the COM + /// classes exposed from the server, and perform the cleanups. + /// + private void PostMessageLoop() + { + // Revoke the registration of COM classes + if (_cookie != 0) + { + COMNative.CoRevokeClassObject(_cookie); + } + + // Dispose the GC timer. + if (_gcTimer != null) + { + _gcTimer.Dispose(); + } + + // Wait for any threads to finish. + Thread.Sleep(1000); + } + + /// + /// Run the COM server. If the server is running, the function + /// returns directly. + /// + /// The method is thread-safe. + public void Run() + { + lock (syncRoot) // Ensure thread-safe + { + // If the server is running, return directly. + if (_bRunning) + return; + + // Indicate that the server is running now. + _bRunning = true; + } + + try + { + // Call PreMessageLoop to initialize the member variables + // and register the class factories. + PreMessageLoop(); + + try + { + // Run the message loop. + RunMessageLoop(); + } + finally + { + // Call PostMessageLoop to revoke the registration. + PostMessageLoop(); + } + } + finally + { + _bRunning = false; + } + } + + /// + /// Increase the lock count + /// + /// The new lock count after the increment + /// The method is thread-safe. + public int Lock() + { + return Interlocked.Increment(ref _nLockCnt); + } + + /// + /// Decrease the lock count. When the lock count drops to zero, post + /// the WM_QUIT message to the message loop in the main thread to + /// shut down the COM server. + /// + /// The new lock count after the increment + public int Unlock() + { + int nRet = Interlocked.Decrement(ref _nLockCnt); + + // If lock drops to zero, attempt to terminate the server. + if (nRet == 0) + { + // Post the WM_QUIT message to the main thread + NativeMethod.PostThreadMessage(_nMainThreadID, NativeMethod.WM_QUIT, UIntPtr.Zero, IntPtr.Zero); + } + + return nRet; + } + + /// + /// Get the current lock count. + /// + /// + public int GetLockCount() + { + return _nLockCnt; + } + } + + class Program + { + /// + /// The main entry point for the application. + /// + static void Main(string[] args) + { + // Run the out-of-process COM server + ExeCOMServer.Instance.Run(); + } + } } \ No newline at end of file diff --git a/vdc/abothe/comserver/NativeMethod.cs b/vdc/abothe/comserver/NativeMethod.cs index 20d22ed0..ebfca2f7 100644 --- a/vdc/abothe/comserver/NativeMethod.cs +++ b/vdc/abothe/comserver/NativeMethod.cs @@ -1,140 +1,140 @@ -/****************************** Module Header ******************************\ -* Module Name: NativeMethod.cs -* Project: CSCOMService -* Copyright (c) Microsoft Corporation. -* -* The P/Invoke signatures of some native APIs. -* -* This source is subject to the Microsoft Public License. -* See http://www.microsoft.com/en-us/openness/licenses.aspx#MPL. -* All other rights reserved. -* -* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, -* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. -\***************************************************************************/ - -#region Using directives -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -#endregion - - -/// -/// Native methods -/// -internal class NativeMethod -{ - /// - /// Get current thread ID. - /// - /// - [DllImport("kernel32.dll")] - internal static extern uint GetCurrentThreadId(); - - /// - /// Get current process ID. - /// - [DllImport("kernel32.dll")] - internal static extern uint GetCurrentProcessId(); - - /// - /// The GetMessage function retrieves a message from the calling thread's - /// message queue. The function dispatches incoming sent messages until a - /// posted message is available for retrieval. - /// - /// - /// Pointer to an MSG structure that receives message information from - /// the thread's message queue. - /// - /// - /// Handle to the window whose messages are to be retrieved. - /// - /// - /// Specifies the integer value of the lowest message value to be - /// retrieved. - /// - /// - /// Specifies the integer value of the highest message value to be - /// retrieved. - /// - /// - [DllImport("user32.dll")] - internal static extern bool GetMessage( - out MSG lpMsg, - IntPtr hWnd, - uint wMsgFilterMin, - uint wMsgFilterMax); - - /// - /// The TranslateMessage function translates virtual-key messages into - /// character messages. The character messages are posted to the calling - /// thread's message queue, to be read the next time the thread calls the - /// GetMessage or PeekMessage function. - /// - /// - /// - [DllImport("user32.dll")] - internal static extern bool TranslateMessage([In] ref MSG lpMsg); - - /// - /// The DispatchMessage function dispatches a message to a window - /// procedure. It is typically used to dispatch a message retrieved by - /// the GetMessage function. - /// - /// - /// - [DllImport("user32.dll")] - internal static extern IntPtr DispatchMessage([In] ref MSG lpMsg); - - /// - /// The PostThreadMessage function posts a message to the message queue - /// of the specified thread. It returns without waiting for the thread to - /// process the message. - /// - /// - /// Identifier of the thread to which the message is to be posted. - /// - /// Specifies the type of message to be posted. - /// - /// Specifies additional message-specific information. - /// - /// - /// Specifies additional message-specific information. - /// - /// - [DllImport("user32.dll")] - internal static extern bool PostThreadMessage( - uint idThread, - uint Msg, - UIntPtr wParam, - IntPtr lParam); - - internal const Int32 WM_QUIT = 0x0012; -} - -[StructLayout(LayoutKind.Sequential)] -internal struct MSG -{ - public IntPtr hWnd; - public uint message; - public IntPtr wParam; - public IntPtr lParam; - public uint time; - public POINT pt; -} - -[StructLayout(LayoutKind.Sequential)] -internal struct POINT -{ - public int X; - public int Y; - - public POINT(int x, int y) - { - this.X = x; - this.Y = y; - } +/****************************** Module Header ******************************\ +* Module Name: NativeMethod.cs +* Project: CSCOMService +* Copyright (c) Microsoft Corporation. +* +* The P/Invoke signatures of some native APIs. +* +* This source is subject to the Microsoft Public License. +* See http://www.microsoft.com/en-us/openness/licenses.aspx#MPL. +* All other rights reserved. +* +* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +\***************************************************************************/ + +#region Using directives +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +#endregion + + +/// +/// Native methods +/// +internal class NativeMethod +{ + /// + /// Get current thread ID. + /// + /// + [DllImport("kernel32.dll")] + internal static extern uint GetCurrentThreadId(); + + /// + /// Get current process ID. + /// + [DllImport("kernel32.dll")] + internal static extern uint GetCurrentProcessId(); + + /// + /// The GetMessage function retrieves a message from the calling thread's + /// message queue. The function dispatches incoming sent messages until a + /// posted message is available for retrieval. + /// + /// + /// Pointer to an MSG structure that receives message information from + /// the thread's message queue. + /// + /// + /// Handle to the window whose messages are to be retrieved. + /// + /// + /// Specifies the integer value of the lowest message value to be + /// retrieved. + /// + /// + /// Specifies the integer value of the highest message value to be + /// retrieved. + /// + /// + [DllImport("user32.dll")] + internal static extern bool GetMessage( + out MSG lpMsg, + IntPtr hWnd, + uint wMsgFilterMin, + uint wMsgFilterMax); + + /// + /// The TranslateMessage function translates virtual-key messages into + /// character messages. The character messages are posted to the calling + /// thread's message queue, to be read the next time the thread calls the + /// GetMessage or PeekMessage function. + /// + /// + /// + [DllImport("user32.dll")] + internal static extern bool TranslateMessage([In] ref MSG lpMsg); + + /// + /// The DispatchMessage function dispatches a message to a window + /// procedure. It is typically used to dispatch a message retrieved by + /// the GetMessage function. + /// + /// + /// + [DllImport("user32.dll")] + internal static extern IntPtr DispatchMessage([In] ref MSG lpMsg); + + /// + /// The PostThreadMessage function posts a message to the message queue + /// of the specified thread. It returns without waiting for the thread to + /// process the message. + /// + /// + /// Identifier of the thread to which the message is to be posted. + /// + /// Specifies the type of message to be posted. + /// + /// Specifies additional message-specific information. + /// + /// + /// Specifies additional message-specific information. + /// + /// + [DllImport("user32.dll")] + internal static extern bool PostThreadMessage( + uint idThread, + uint Msg, + UIntPtr wParam, + IntPtr lParam); + + internal const Int32 WM_QUIT = 0x0012; +} + +[StructLayout(LayoutKind.Sequential)] +internal struct MSG +{ + public IntPtr hWnd; + public uint message; + public IntPtr wParam; + public IntPtr lParam; + public uint time; + public POINT pt; +} + +[StructLayout(LayoutKind.Sequential)] +internal struct POINT +{ + public int X; + public int Y; + + public POINT(int x, int y) + { + this.X = x; + this.Y = y; + } } \ No newline at end of file diff --git a/vdc/abothe/comserver/Properties/AssemblyInfo.cs b/vdc/abothe/comserver/Properties/AssemblyInfo.cs index cf40bdc4..bbc2c3bb 100644 --- a/vdc/abothe/comserver/Properties/AssemblyInfo.cs +++ b/vdc/abothe/comserver/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("COM Server for DParser")] -[assembly: AssemblyDescription("COM Server for DParser")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Rainer Schuetze")] -[assembly: AssemblyProduct("DParserCOMServer")] -[assembly: AssemblyCopyright("Copyright © R.Schuetze 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("002a2de9-8bb6-484d-AA03-7e4ad4084715")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("COM Server for DParser")] +[assembly: AssemblyDescription("COM Server for DParser")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Rainer Schuetze")] +[assembly: AssemblyProduct("DParserCOMServer")] +[assembly: AssemblyCopyright("Copyright © R.Schuetze 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("002a2de9-8bb6-484d-AA03-7e4ad4084715")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/vdc/abothe/comserver/VDServer.cs b/vdc/abothe/comserver/VDServer.cs index 8d915c71..4162e38e 100644 --- a/vdc/abothe/comserver/VDServer.cs +++ b/vdc/abothe/comserver/VDServer.cs @@ -381,8 +381,8 @@ public void GetLastMessage(out string message) public void GetDefinition(string filename, int startLine, int startIndex, int endLine, int endIndex) { - filename = normalizePath(filename); - var ast = GetModule(filename); + filename = normalizePath(filename); + var ast = GetModule(filename); if (ast == null) throw new COMException("module not found", 1); @@ -398,32 +398,40 @@ public void GetDefinition(string filename, int startLine, int startIndex, int en // codeOffset+1 because otherwise it does not work on the first character _editorData.CaretOffset = getCodeOffset(_editorData.ModuleCode, _tipStart) + 2; - ISyntaxRegion sr = DResolver.GetScopedCodeObject(_editorData); - LooseResolution.NodeResolutionAttempt attempt; - var rr = sr != null ? LooseResolution.ResolveTypeLoosely(_editorData, sr, out attempt, true) : null; + ISyntaxRegion sr = DResolver.GetScopedCodeObject(_editorData); + LooseResolution.NodeResolutionAttempt attempt; + var rr = sr != null ? LooseResolution.ResolveTypeLoosely(_editorData, sr, out attempt, true) : null; _tipText.Clear(); if (rr != null) { - var n = DResolver.GetResultMember(rr, true); - - if (n == null) - return; - - bool decl = false; - var mthd = n as DMethod; - if (mthd != null) - decl = mthd.Body == null; - else if (n.ContainsAttribute(DTokens.Extern)) - decl = true; - if (decl) - _tipText.Append("EXTERN:"); - - _tipStart = n.Location; - _tipEnd = n.EndLocation; - INode node = n.NodeRoot; - if(node is DModule) - _tipText.Append((node as DModule).FileName); + DNode n = null; + foreach (var t in AmbiguousType.TryDissolve(rr)) + { + n = DResolver.GetResultMember(t, true); + if (n != null) + break; + } + + if (n != null) + { + if (_tipText.Length > 0) + _tipText.Append("\n"); + bool decl = false; + var mthd = n as DMethod; + if (mthd != null) + decl = mthd.Body == null; + else if (n.ContainsAttribute(DTokens.Extern)) + decl = true; + if (decl) + _tipText.Append("EXTERN:"); + + _tipStart = n.Location; + _tipEnd = n.EndLocation; + INode node = n.NodeRoot; + if(node is DModule) + _tipText.Append((node as DModule).FileName); + } } } public void GetDefinitionResult(out int startLine, out int startIndex, out int endLine, out int endIndex, out string filename) @@ -518,11 +526,19 @@ void _setupEditorData() if ((_flags & 16) != 0) versions += "D_Ddoc\n"; if ((_flags & 32) != 0) - versions += "D_NoBoundsChecks\n"; - if ((_flags & 64) != 0) - versions += "GNU\n"; - else - versions += "DigitalMars\n"; + versions += "D_NoBoundsChecks\n"; + if ((_flags & 64) != 0) + versions += "GNU\n"; + else if ((_flags & 0x4000000) != 0) + versions += "LDC\n"; + else + versions += "DigitalMars\n"; + if ((_flags & 0x8000000) != 0) + versions += "CRuntime_Microsoft\n"; + else if ((_flags & 0x4000040) != 0) // GNU or LDC + versions += "CRuntime_MinGW\n"; + else + versions += "CRuntime_DigitalMars\n"; string[] uniqueDirs = uniqueDirectories(_imports); _editorData.ParseCache = new VDserverParseCacheView(uniqueDirs); diff --git a/vdc/abothe/comserver/VDServerCompletionDataGenerator.cs b/vdc/abothe/comserver/VDServerCompletionDataGenerator.cs index 76b6d07c..c1c60ef2 100644 --- a/vdc/abothe/comserver/VDServerCompletionDataGenerator.cs +++ b/vdc/abothe/comserver/VDServerCompletionDataGenerator.cs @@ -1,261 +1,261 @@ -using D_Parser.Completion; -using D_Parser.Dom; -using D_Parser.Parser; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace DParserCOMServer -{ - class VDServerCompletionDataGenerator : ICompletionDataGenerator - { - public VDServerCompletionDataGenerator(string pre) - { - prefix = pre; - } - - public void NotifyTimeout() - { - - } - - /// - /// Adds a token entry - /// - public void Add(byte Token) - { - addExpansion(DTokens.Keywords[Token], "KW", ""); - } - - /// - /// Adds a property attribute - /// - public void AddPropertyAttribute(string AttributeText) - { - addExpansion(AttributeText, "PROP", ""); - } - - public void AddTextItem(string Text, string Description) - { - addExpansion(Text, "TEXT", Description); - } - - class NodeTypeNameVisitor : NodeVisitor - { - const string InvalidType = "I"; - const string TemplateType = "TMPL"; - - public static readonly NodeTypeNameVisitor Instance = new NodeTypeNameVisitor(); - - public string Visit(DEnumValue dEnumValue) - { - return "EVAL"; - } - - public string Visit(DVariable dVariable) - { - return "VAR"; - } - - public string Visit(DMethod n) - { - if (n.ContainsPropertyAttribute(BuiltInAtAttribute.BuiltInAttributes.Property)) - return "PROP"; - return "MTHD"; - } - - public string Visit(DClassLike dClassLike) - { - switch (dClassLike.ClassType) - { - case DTokens.Struct: - return "STRU"; - default: - return "CLSS"; - case DTokens.Interface: - return "IFAC"; - case DTokens.Template: - return TemplateType; - case DTokens.Union: - return "UNIO"; - } - } - - public string Visit(DEnum dEnum) - { - return "ENUM"; - } - - public string Visit(DModule dModule) - { - return "MOD"; - } - - public string Visit(DBlockNode dBlockNode) - { - return InvalidType; - } - - public string Visit(TemplateParameter.Node templateParameterNode) - { - return TemplateType; // ? or a more special type ? - } - - public string Visit(NamedTemplateMixinNode n) - { - return "NMIX"; - } - - public string Visit(EponymousTemplate ep) - { - return TemplateType; - } - - public string Visit(ModuleAliasNode moduleAliasNode) - { - return "VAR"; - } - - public string Visit(ImportSymbolNode importSymbolNode) - { - return "VAR"; - } - - public string Visit(ImportSymbolAlias importSymbolAlias) - { - return "VAR"; - } - - #region Not needed - public string VisitAttribute(Modifier attr) - { - throw new NotImplementedException(); - } - - public string VisitAttribute(DeprecatedAttribute a) - { - throw new NotImplementedException(); - } - - public string VisitAttribute(PragmaAttribute attr) - { - throw new NotImplementedException(); - } - - public string VisitAttribute(BuiltInAtAttribute a) - { - throw new NotImplementedException(); - } - - public string VisitAttribute(UserDeclarationAttribute a) - { - throw new NotImplementedException(); - } - - public string VisitAttribute(VersionCondition a) - { - throw new NotImplementedException(); - } - - public string VisitAttribute(DebugCondition a) - { - throw new NotImplementedException(); - } - - public string VisitAttribute(StaticIfCondition a) - { - throw new NotImplementedException(); - } - - public string VisitAttribute(NegatedDeclarationCondition a) - { - throw new NotImplementedException(); - } - #endregion - } - - public void SetSuggestedItem(string item) { } - - /// - /// Adds a node to the completion data - /// - /// - public void Add(INode Node) - { - if (Node.NameHash == 0) - return; - var name = Node.Name; - if (!name.StartsWith(prefix)) - return; - - var sb = new StringBuilder(NodeToolTipContentGen.Instance.GenTooltipSignature(Node as DNode)); - - GenerateNodeTooltipBody(Node as DNode, sb); - - addExpansion(name, Node.Accept(NodeTypeNameVisitor.Instance), sb.ToString()); - } - - public static void GenerateNodeTooltipBody(DNode Node, StringBuilder sb) - { - Dictionary cats; - string summary; - NodeToolTipContentGen.Instance.GenToolTipBody(Node, out summary, out cats); - - if (!string.IsNullOrEmpty(summary) || (cats != null && cats.Count > 0)) - sb.Append("\n"); - - if (!string.IsNullOrEmpty(summary)) - sb.Append(summary); - - if (cats != null) - { - foreach (var kv in cats) - { - sb.Append("\n").Append(kv.Key).Append("\n"); - sb.Append(kv.Value); - } - } - } - - /// - /// Adds a module (name stub) to the completion data - /// - /// - /// - public void AddModule(DModule module, string nameOverride) - { - if (string.IsNullOrEmpty(nameOverride)) - addExpansion(module.Name, "MOD", ""); - else - addExpansion(nameOverride, "MOD", ""); - } - - public void AddPackage(string packageName) - { - addExpansion(packageName, "PKG", ""); - } - - public void AddCodeGeneratingNodeItem(INode node, string codeToGenerate) - { - addExpansion(node.Name + "|" + codeToGenerate, "OVR", codeToGenerate); - } - - public void AddIconItem(string iconName, string text, string description) - { - addExpansion(iconName + "|" + text, "ICN", description); - } - - void addExpansion(string name, string type, string desc) - { - if (name != null && name.StartsWith(prefix)) - { - expansions.Append(name.Replace("\r", string.Empty).Replace('\n', '\a')).Append(':').Append(type).Append(':'); - expansions.Append(desc.Replace("\r", string.Empty).Replace('\n', '\a')).Append('\n'); - } - } - - public readonly StringBuilder expansions = new StringBuilder(); - public string prefix; - } -} +using D_Parser.Completion; +using D_Parser.Dom; +using D_Parser.Parser; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DParserCOMServer +{ + class VDServerCompletionDataGenerator : ICompletionDataGenerator + { + public VDServerCompletionDataGenerator(string pre) + { + prefix = pre; + } + + public void NotifyTimeout() + { + + } + + /// + /// Adds a token entry + /// + public void Add(byte Token) + { + addExpansion(DTokens.Keywords[Token], "KW", ""); + } + + /// + /// Adds a property attribute + /// + public void AddPropertyAttribute(string AttributeText) + { + addExpansion(AttributeText, "PROP", ""); + } + + public void AddTextItem(string Text, string Description) + { + addExpansion(Text, "TEXT", Description); + } + + class NodeTypeNameVisitor : NodeVisitor + { + const string InvalidType = "I"; + const string TemplateType = "TMPL"; + + public static readonly NodeTypeNameVisitor Instance = new NodeTypeNameVisitor(); + + public string Visit(DEnumValue dEnumValue) + { + return "EVAL"; + } + + public string Visit(DVariable dVariable) + { + return "VAR"; + } + + public string Visit(DMethod n) + { + if (n.ContainsPropertyAttribute(BuiltInAtAttribute.BuiltInAttributes.Property)) + return "PROP"; + return "MTHD"; + } + + public string Visit(DClassLike dClassLike) + { + switch (dClassLike.ClassType) + { + case DTokens.Struct: + return "STRU"; + default: + return "CLSS"; + case DTokens.Interface: + return "IFAC"; + case DTokens.Template: + return TemplateType; + case DTokens.Union: + return "UNIO"; + } + } + + public string Visit(DEnum dEnum) + { + return "ENUM"; + } + + public string Visit(DModule dModule) + { + return "MOD"; + } + + public string Visit(DBlockNode dBlockNode) + { + return InvalidType; + } + + public string Visit(TemplateParameter.Node templateParameterNode) + { + return TemplateType; // ? or a more special type ? + } + + public string Visit(NamedTemplateMixinNode n) + { + return "NMIX"; + } + + public string Visit(EponymousTemplate ep) + { + return TemplateType; + } + + public string Visit(ModuleAliasNode moduleAliasNode) + { + return "VAR"; + } + + public string Visit(ImportSymbolNode importSymbolNode) + { + return "VAR"; + } + + public string Visit(ImportSymbolAlias importSymbolAlias) + { + return "VAR"; + } + + #region Not needed + public string VisitAttribute(Modifier attr) + { + throw new NotImplementedException(); + } + + public string VisitAttribute(DeprecatedAttribute a) + { + throw new NotImplementedException(); + } + + public string VisitAttribute(PragmaAttribute attr) + { + throw new NotImplementedException(); + } + + public string VisitAttribute(BuiltInAtAttribute a) + { + throw new NotImplementedException(); + } + + public string VisitAttribute(UserDeclarationAttribute a) + { + throw new NotImplementedException(); + } + + public string VisitAttribute(VersionCondition a) + { + throw new NotImplementedException(); + } + + public string VisitAttribute(DebugCondition a) + { + throw new NotImplementedException(); + } + + public string VisitAttribute(StaticIfCondition a) + { + throw new NotImplementedException(); + } + + public string VisitAttribute(NegatedDeclarationCondition a) + { + throw new NotImplementedException(); + } + #endregion + } + + public void SetSuggestedItem(string item) { } + + /// + /// Adds a node to the completion data + /// + /// + public void Add(INode Node) + { + if (Node.NameHash == 0) + return; + var name = Node.Name; + if (!name.StartsWith(prefix)) + return; + + var sb = new StringBuilder(NodeToolTipContentGen.Instance.GenTooltipSignature(Node as DNode)); + + GenerateNodeTooltipBody(Node as DNode, sb); + + addExpansion(name, Node.Accept(NodeTypeNameVisitor.Instance), sb.ToString()); + } + + public static void GenerateNodeTooltipBody(DNode Node, StringBuilder sb) + { + Dictionary cats; + string summary; + NodeToolTipContentGen.Instance.GenToolTipBody(Node, out summary, out cats); + + if (!string.IsNullOrEmpty(summary) || (cats != null && cats.Count > 0)) + sb.Append("\n"); + + if (!string.IsNullOrEmpty(summary)) + sb.Append(summary); + + if (cats != null) + { + foreach (var kv in cats) + { + sb.Append("\n").Append(kv.Key).Append("\n"); + sb.Append(kv.Value); + } + } + } + + /// + /// Adds a module (name stub) to the completion data + /// + /// + /// + public void AddModule(DModule module, string nameOverride) + { + if (string.IsNullOrEmpty(nameOverride)) + addExpansion(module.Name, "MOD", ""); + else + addExpansion(nameOverride, "MOD", ""); + } + + public void AddPackage(string packageName) + { + addExpansion(packageName, "PKG", ""); + } + + public void AddCodeGeneratingNodeItem(INode node, string codeToGenerate) + { + addExpansion(node.Name + "|" + codeToGenerate, "OVR", codeToGenerate); + } + + public void AddIconItem(string iconName, string text, string description) + { + addExpansion(iconName + "|" + text, "ICN", description); + } + + void addExpansion(string name, string type, string desc) + { + if (name != null && name.StartsWith(prefix)) + { + expansions.Append(name.Replace("\r", string.Empty).Replace('\n', '\a')).Append(':').Append(type).Append(':'); + expansions.Append(desc.Replace("\r", string.Empty).Replace('\n', '\a')).Append('\n'); + } + } + + public readonly StringBuilder expansions = new StringBuilder(); + public string prefix; + } +} diff --git a/vdc/ivdserver.d b/vdc/ivdserver.d index b28a7ed4..db78ebb2 100644 --- a/vdc/ivdserver.d +++ b/vdc/ivdserver.d @@ -28,11 +28,11 @@ import sdk.win32.oleauto; // to stop-the-world garbage collections on large amounts of memory (in case of // the current D runtime, 200MB are enough to make this annoying). // -// Visual D creates a single thread for communicating with the server and expects +// Visual D creates a single thread for communicating with the server and expects // expensive calls to be asynchronous: methods GetTip, GetDefinition, GetSemanticExpansions // and UpdateModule return immediately, but start some background processing. // The client (aka Visual D) polls the result with GetTipResult, GetDefinitionResult, -// GetSemanticExpansionsResult // and GetParseErrors, repectively, until they return successfully. +// GetSemanticExpansionsResult // and GetParseErrors, repectively, until they return successfully. // While doing so, GetLastMessage is called to get status line messages (e.g. "parsing module...") // // All methods reference modules by their file name. @@ -47,7 +47,7 @@ interface IVDServer : IUnknown public: // set compilation options for the given file // - // filename: file name + // filename: file name // imp: new-line delimited list of import folders // stringImp: new-line delimited list of string import folders // versionids: new-line delimited list of version identifiers defined on the command line @@ -58,18 +58,18 @@ public: // is used in multiple projects, which one is chosen is undefined. // If the file is not contained in a project, the options of the current // startup-project are used. - // + // // This function is usually called after UpdateModule, assuming that parsing does // not depend on compilation options, so any semantic analysis should be deferred // until ConfigureSemanticProject is called. HRESULT ConfigureSemanticProject(in BSTR filename, in BSTR imp, in BSTR stringImp, in BSTR versionids, in BSTR debugids, DWORD flags); - + // delete all semantic and parser information HRESULT ClearSemanticProject(); - + // parse file given the current text in the editor // - // filename: file name + // filename: file name // srcText: current text in editor // verbose: display parsing message? // @@ -80,17 +80,17 @@ public: // not depend on compilation options, so any semantic analysis should be deferred // until ConfigureSemanticProject is invoked. HRESULT UpdateModule(in BSTR filename, in BSTR srcText, in BOOL verbose); - + // request tool tip text for a given text location // - // filename: file name + // filename: file name // startLine, startIndex, endLine, endIndex: selected range in the editor // if start==end, mouse hovers without selection // // it is assumed that the semantic analysis is forwarded to some other thread // and that the status can be polled by GetTipResult HRESULT GetTip(in BSTR filename, int startLine, int startIndex, int endLine, int endIndex); - + // get the result of the previous GetTip // // startLine, startIndex, endLine, endIndex: return the range of the evaluated expression @@ -99,10 +99,10 @@ public: // // return S_FALSE as long as the semantic analysis is still running HRESULT GetTipResult(ref int startLine, ref int startIndex, ref int endLine, ref int endIndex, BSTR* answer); - + // request a list of expansions for a given text location // - // filename: file name + // filename: file name // tok: the prefix of the identifier to expand, allowing filtering results // line, idx: the location of the caret in the text editor // expr: the expression to evaluate at the insertion point in case of parser issues @@ -110,46 +110,46 @@ public: // it is assumed that the semantic analysis is forwarded to some other thread // and that the status can be polled by GetSemanticExpansionsResult HRESULT GetSemanticExpansions(in BSTR filename, in BSTR tok, uint line, uint idx, in BSTR expr); - + // get the result of the previous GetSemanticExpansions // // stringList: a new-line delimited list of expansions // // return S_FALSE as long as the semantic analysis is still running HRESULT GetSemanticExpansionsResult(BSTR* stringList); - + // not used HRESULT IsBinaryOperator(in BSTR filename, uint startLine, uint startIndex, uint endLine, uint endIndex, BOOL* pIsOp); - + // return the parse errors found in the file // - // filename: file name + // filename: file name // errors: new-line delimited list of errors, each line has the format: // startLine,startIndex,endLine,endIndex: error text // - // the range given by startLine,startIndex,endLine,endIndex will be marked + // the range given by startLine,startIndex,endLine,endIndex will be marked // as erronous by underlining it in the editor // // return S_FALSE as long as the parsisng is still running HRESULT GetParseErrors(in BSTR filename, BSTR* errors); - + // return the locations where "in" and "is" are used as binary operators - // - // filename: file name + // + // filename: file name // locs: an array of pairs of DWORDs line,index that gives the text location of the "i" // // this method is called once after GetParseErrors returned successfully HRESULT GetBinaryIsInLocations(in BSTR filename, VARIANT* locs); - + // return a message to be displayed in the status line of the IDE // - // it is assumed that a message is returned only once. + // it is assumed that a message is returned only once. // return S_FALSE if there is no new message to display HRESULT GetLastMessage(BSTR* message); // request location of definition for a given text location // - // filename: file name + // filename: file name // startLine, startIndex, endLine, endIndex: selected range in the editor // if start==end, mouse hovers without selection // @@ -167,7 +167,7 @@ public: // request a list of references for a given text location // - // filename: file name + // filename: file name // tok: the identifier to reference // line, idx: the location of the caret in the text editor // expr: the expression to evaluate at the insertion point in case of parser issues @@ -180,7 +180,7 @@ public: /////////////////////////////////////////////////////////////////////// uint ConfigureFlags()(bool unittestOn, bool debugOn, bool x64, bool cov, bool doc, bool nobounds, bool gdc, - int versionLevel, int debugLevel, bool noDeprecated, + int versionLevel, int debugLevel, bool noDeprecated, bool ldc, bool msvcrt, bool mixinAnalysis, bool ufcsExpansions) { return (unittestOn ? 1 : 0) @@ -194,6 +194,8 @@ uint ConfigureFlags()(bool unittestOn, bool debugOn, bool x64, bool cov, bool do | ((versionLevel & 0xff) << 8) | ((debugLevel & 0xff) << 16) | (mixinAnalysis ? 0x1_00_00_00 : 0) - | (ufcsExpansions ? 0x2_00_00_00 : 0); + | (ufcsExpansions ? 0x2_00_00_00 : 0) + | (ldc ? 0x4_00_00_00 : 0) + | (msvcrt ? 0x8_00_00_00 : 0); } diff --git a/vdc/semantic.d b/vdc/semantic.d index 5cd8c638..5c1f65db 100644 --- a/vdc/semantic.d +++ b/vdc/semantic.d @@ -79,7 +79,7 @@ void semanticErrorLoc(T...)(string filename, ref const(TextPos) pos, T args) foreach(a; args) if(typeid(a) == typeid(ErrorType) || typeid(a) == typeid(ErrorValue)) return; - + string msg = semanticErrorWriteLoc(filename, pos); msg ~= text(args); if(fnSemanticWriteError) @@ -131,7 +131,7 @@ ErrorType semanticErrorType(T...)(T args) alias Node Symbol; -class Context +class Context { Scope scop; Value[Node] vars; @@ -148,12 +148,12 @@ class Context return parent.getThis(); return null; } - + void setThis(Value v) { setValue(null, v); } - + Value getValue(Node n) { if(auto pn = n in vars) @@ -180,7 +180,7 @@ class AggrContext : Context instance = inst; virtualCall = true; } - + override Value getThis() { if(auto t = cast(Class)instance.getType()) @@ -222,16 +222,16 @@ Context errorContext; class Scope { Scope parent; - + Annotation annotations; Attribute attributes; Module mod; Node node; Set!Symbol[string] symbols; Import[] imports; - + // Context ctx; // compile time only - + static Scope current; this() @@ -243,7 +243,7 @@ class Scope SearchParentScope = 1, SearchPrivateImport = 2, } - + Scope pushClone() { Scope sc = new Scope; @@ -262,12 +262,12 @@ class Scope sc.parent = this; return current = sc; } - + Scope pop() { return current = parent; } - + Type getThisType() { if(!parent) @@ -278,18 +278,18 @@ class Scope void addSymbol(string ident, Symbol s) { logInfo("Scope(%s).addSymbol(%s, sym %s=%s)", cast(void*)this, ident, s, cast(void*)s); - + if(auto sym = ident in symbols) addunique(*sym, s); else symbols[ident] = Set!Symbol([s : true]); } - + void addImport(Import imp) { imports ~= imp; } - + struct SearchData { string ident; Scope sc; } static Stack!SearchData searchStack; @@ -314,7 +314,7 @@ class Scope } } - static bool collectSymbols(string ident) + static bool collectSymbols(string ident) { return ident.endsWith("*"); } @@ -332,7 +332,7 @@ class Scope searchCollect(ident, syms); else if(auto pn = ident in symbols) return *pn; - + searchStack.push(sd); if(publicImports) foreach(imp; imports) @@ -355,7 +355,7 @@ class Scope cntFunc++; if(cntFunc != n.length) return matches; - + Node[] args; if(fnargs) args = fnargs.members; @@ -385,7 +385,7 @@ class Scope } return matches; } - + Node resolveOverload(string ident, Node id, Scope.SearchSet n) { if(n.length == 0) @@ -395,7 +395,7 @@ class Scope } foreach(s, b; n) s.semanticSearches++; - + if(n.length > 1) { auto matches = matchFunctionArguments(id, n); @@ -407,7 +407,7 @@ class Scope id.semanticError("ambiguous identifier " ~ ident); foreach(s, b; n) s.semanticError("possible candidate"); - + if(!collectSymbols(ident)) return null; } @@ -418,10 +418,10 @@ class Scope { auto n = search(ident, inParents, true, true); logInfo("Scope(%s).search(%s) found %s %s", cast(void*)this, ident, n.keys(), n.length > 0 ? cast(void*)n.first() : null); - + return resolveOverload(ident, id, n); } - + Node resolveWithTemplate(string ident, Scope sc, Node id, bool inParents = true) { auto n = search(ident, inParents, true, true); @@ -464,7 +464,7 @@ class SourceModule string txt; Module parsed; Module analyzed; - + Parser parser; ParseError[] parseErrors; @@ -484,7 +484,7 @@ class Project : Node Module mObjectModule; // object.d SourceModule[string] mSourcesByModName; SourceModule[string] mSourcesByFileName; - + this() { TextSpan initspan; @@ -495,7 +495,7 @@ class Project : Node { options.importDirs ~= r"c:\l\dmd-2.055\src\druntime\import\"; options.importDirs ~= r"c:\l\dmd-2.055\src\phobos\"; - + options.importDirs ~= r"c:\tmp\d\runnable\"; options.importDirs ~= r"c:\tmp\d\runnable\imports\"; @@ -606,14 +606,14 @@ class Project : Node auto mod = static_cast!(Module)(n); return addSource(fname, mod, p.errors, importFrom); } - + Module addAndParseFile(string fname, Node importFrom = null) { //debug writeln(fname, ":"); string txt = readUtf8(fname); return addText(fname, txt, importFrom); } - + bool addFile(string fname) { auto src = new SourceModule; @@ -643,7 +643,7 @@ class Project : Node { if(auto mod = getModule(modname)) return mod; - + string dfile = replace(modname, ".", "/") ~ ".di"; string srcfile = searchImportFile(dfile, importFrom); if(srcfile.length == 0) @@ -662,12 +662,12 @@ class Project : Node srcfile = normalizePath(srcfile); return addAndParseFile(srcfile, importFrom); } - + string searchImportFile(string dfile, Node importFrom) { if(std.file.exists(dfile)) return dfile; - + Options opt = options; if(importFrom) if(auto mod = importFrom.getModule()) @@ -678,7 +678,7 @@ class Project : Node return dir ~ dfile; return null; } - + void initScope() { getObjectModule(null); @@ -743,7 +743,7 @@ class Project : Node writer(members[m]); writer.nl; } - + writer.writeDeclarations = false; writer.writeImplementations = true; for(int m = 0; m < members.length; m++) @@ -783,15 +783,15 @@ class Project : Node writer("}"); writer.nl; } - + std.file.write(fname, src); } - + override void toD(CodeWriter writer) { throw new SemanticException("Project.toD not implemeted"); } - + int run() { Scope.SearchSet funcs; @@ -817,7 +817,7 @@ class Project : Node auto dav = new DynArrayValue(tda); args.addValue(dav); } - + try { Value v = funcs.first().interpret(nullContext).opCall(nullContext, args); @@ -889,7 +889,7 @@ struct VersionDebug identifiers[ident] = vi; return false; } - + void define(string ident, TextPos pos) { if(auto vi = ident in identifiers) @@ -899,7 +899,7 @@ struct VersionDebug if(pos < vi.defined) vi.defined = pos; } - + VersionInfo vi; vi.firstUsage.line = int.max; vi.defined = pos; @@ -908,18 +908,20 @@ struct VersionDebug } class Options -{ +{ string[] importDirs; string[] stringImportDirs; - + public /* debug & version handling */ { bool unittestOn; bool x64; + bool msvcrt; bool debugOn; bool coverage; bool doDoc; bool noBoundsCheck; bool gdcCompiler; + bool ldcCompiler; bool noDeprecated; bool mixinAnalysis; bool UFCSExpansions; @@ -966,15 +968,15 @@ class Options int pre = versionPredefined(ident); if(pre == 0) return versionIds.defined(ident, TextPos()); - + return pre > 0; } - + bool versionEnabled(int level) { return level <= versionIds.level; } - + bool debugEnabled(string ident) { return debugIds.defined(ident, TextPos()); @@ -984,7 +986,7 @@ class Options { return level <= debugIds.level; } - + int versionPredefined(string ident) { int* p = ident in sPredefinedVersions; @@ -1005,12 +1007,16 @@ class Options return doDoc ? 1 : -1; case "D_NoBoundsChecks": return noBoundsCheck ? 1 : -1; - case "CRuntime_DigitalMars": case "Win32": case "X86": case "D_InlineAsm_X86": return x64 ? -1 : 1; + case "CRuntime_DigitalMars": + return msvcrt ? -1 : 1; case "CRuntime_Microsoft": + return msvcrt ? 1 : -1; + case "MinGW": + return gdcCompiler || (ldcCompiler && !msvcrt) ? 1 : -1; case "Win64": case "X86_64": case "D_InlineAsm_X86_64": @@ -1018,8 +1024,10 @@ class Options return x64 ? 1 : -1; case "GNU": return gdcCompiler ? 1 : -1; + case "LDC": + return ldcCompiler ? 1 : -1; case "DigitalMars": - return gdcCompiler ? -1 : 1; + return gdcCompiler || ldcCompiler ? -1 : 1; default: assert(false, "inconsistent predefined versions"); } diff --git a/vdc/vdserver.d b/vdc/vdserver.d index 7a91a39d..f50fffd5 100644 --- a/vdc/vdserver.d +++ b/vdc/vdserver.d @@ -55,18 +55,18 @@ version(DebugServer) import core.stdc.stdio : fprintf, fopen, fputc, fflush, FILE; __gshared FILE* dbgfh; - void dbglog(string s) + void dbglog(string s) { debug { - version(vdlog) + version(vdlog) logCall("VDServer: ", s); else sdk.win32.winbase.OutputDebugStringA(toMBSz("VDServer: " ~ s ~ "\n")); } else { - if(!dbgfh) + if(!dbgfh) dbgfh = fopen("c:/tmp/vdserver.log", "w"); SysTime now = Clock.currTime(); @@ -160,7 +160,7 @@ class VDServer : ComObject, IVDServer extern(D) void schedule(void delegate() dg) { - version(SingleThread) + version(SingleThread) send(mTid, *cast(delegate_fake*)&dg); else runTask(dg); @@ -181,10 +181,11 @@ class VDServer : ComObject, IVDServer string imports = to_string(imp); string strImports = to_string(stringImp); - uint oldflags = ConfigureFlags!()(opts.unittestOn, opts.debugOn, opts.x64, + uint oldflags = ConfigureFlags!()(opts.unittestOn, opts.debugOn, opts.x64, opts.coverage, opts.doDoc, opts.noBoundsCheck, opts.gdcCompiler, 0, 0, // no need to compare version levels, done in setVersionIds - opts.noDeprecated, opts.mixinAnalysis, opts.UFCSExpansions); + opts.noDeprecated, opts.ldcCompiler, opts.msvcrt, + opts.mixinAnalysis, opts.UFCSExpansions); opts.unittestOn = (flags & 1) != 0; opts.debugOn = (flags & 2) != 0; @@ -196,6 +197,8 @@ class VDServer : ComObject, IVDServer opts.noDeprecated = (flags & 128) != 0; opts.mixinAnalysis = (flags & 0x1_00_00_00) != 0; opts.UFCSExpansions = (flags & 0x2_00_00_00) != 0; + opts.ldcCompiler = (flags & 0x4_00_00_00) != 0; + opts.msvcrt = (flags & 0x8_00_00_00) != 0; int versionlevel = (flags >> 8) & 0xff; int debuglevel = (flags >> 16) & 0xff; @@ -206,8 +209,8 @@ class VDServer : ComObject, IVDServer int changed = (oldflags != (flags & 0xff0000ff)); changed += opts.setImportDirs(splitLines(imports)); changed += opts.setImportDirs(splitLines(imports)); - changed += opts.setVersionIds(versionlevel, splitLines(verids)); - changed += opts.setDebugIds(debuglevel, splitLines(dbgids)); + changed += opts.setVersionIds(versionlevel, splitLines(verids)); + changed += opts.setDebugIds(debuglevel, splitLines(dbgids)); } return S_OK; } @@ -216,7 +219,7 @@ class VDServer : ComObject, IVDServer { synchronized(mSemanticProject) mSemanticProject.disconnectAll(); - + mSemanticProject = new vdc.semantic.Project; mSemanticProject.saveErrors = true; return S_OK; @@ -226,7 +229,7 @@ class VDServer : ComObject, IVDServer { string fname = to_string(filename); string text = to_string(srcText); - + auto parser = new Parser; parser.saveErrors = true; @@ -523,7 +526,7 @@ class VDServer : ComObject, IVDServer if(!pIsOp) return E_POINTER; string fname = to_string(filename); - + synchronized(mSemanticProject) if(auto src = mSemanticProject.getModuleByFilename(fname)) if(src.parsed) @@ -582,7 +585,7 @@ class VDServer : ComObject, IVDServer for(LONG index = 0; index < locData.length; index++) SafeArrayPutElement(sa, &index, &locData[index]); - + locs.vt = VT_ARRAY; locs.parray = sa; return S_OK; @@ -594,7 +597,7 @@ class VDServer : ComObject, IVDServer { if(mNextReadyMessage > Clock.currTime()) return S_FALSE; - + mLastMessage = "Ready"; mNextReadyMessage = Clock.currTime().add!"years"(1); } diff --git a/vdc/versions.d b/vdc/versions.d index 5823bea2..adfa47bc 100644 --- a/vdc/versions.d +++ b/vdc/versions.d @@ -19,7 +19,7 @@ static @property int[string] sPredefinedVersions() // 1: always defined // -1: always undefined // 0: to be determined by compiler option - predefinedVersions = + predefinedVersions = [ "DigitalMars" : 0, "GNU" : 0, @@ -47,7 +47,7 @@ static @property int[string] sPredefinedVersions() "Hurd" : -1, "Android" : -1, "Cygwin" : -1, - "MinGW" : -1, + "MinGW" : 0, "X86" : 0, "X86_64" : 0, @@ -91,7 +91,7 @@ static @property int[string] sPredefinedVersions() "LittleEndian" : 1, "BigEndian" : -1, - + "ELFv1" : -1, "ELFv2" : -1, @@ -109,7 +109,7 @@ static @property int[string] sPredefinedVersions() "D_SoftFloat" : -1, "D_PIC" : -1, "D_SIMD" : 1, - + "D_Version2" : 1, "D_NoBoundsChecks" : 0, diff --git a/vdextensions/vdextensions.sln b/vdextensions/vdextensions.sln index b3b4f06b..432ff019 100644 --- a/vdextensions/vdextensions.sln +++ b/vdextensions/vdextensions.sln @@ -1,28 +1,28 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vdextensions", "vdextensions.csproj", "{3A338E86-A08A-4F9A-8DB1-A5C280773BA3}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|x86.ActiveCfg = Debug|x86 - {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|x86.Build.0 = Debug|x86 - {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|Any CPU.ActiveCfg = Debug|x86 - {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|Any CPU.Build.0 = Debug|x86 - {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|x86.ActiveCfg = Release|x86 - {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|x86.Build.0 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vdextensions", "vdextensions.csproj", "{3A338E86-A08A-4F9A-8DB1-A5C280773BA3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|x86.ActiveCfg = Debug|x86 + {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|x86.Build.0 = Debug|x86 + {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|Any CPU.ActiveCfg = Debug|x86 + {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|Any CPU.Build.0 = Debug|x86 + {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|x86.ActiveCfg = Release|x86 + {3A338E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/visuald/Resources/pkgcmd.ctc b/visuald/Resources/pkgcmd.ctc deleted file mode 100644 index 6f7fcd0b..00000000 --- a/visuald/Resources/pkgcmd.ctc +++ /dev/null @@ -1,130 +0,0 @@ -// Package Command Bar Definition -// - -//#include "stdidcmd.h" -//#include "vsshlids.h" -//#include "msobtnid.h" -//#include "virtkeys.h" -//#include "PkgCmdID.h" -#include "Resources.h" - -//#define guidToolWindowPkg { 0xAD5B3373, 0x1F9E, 0x442f, { 0x96, 0x9F, 0x94, 0xA9, 0x2F, 0xBB, 0xAA, 0x2C } } -//#define guidToolWindowMenuGrp { 0x26CB6B7B, 0xD8D4, 0x47dd, { 0x8A, 0x8B, 0x4F, 0x4D, 0xB7, 0x4F, 0xEF, 0xB9 } } -//#define guidToolWindowCmdSet { 0x8CBE33CC, 0xCA38, 0x4a8a, { 0x9F, 0xB9, 0x27, 0x67, 0x97, 0x73, 0x56, 0x6E } } - -#define g_packageCLSID { 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x7f, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } } -#define g_commandSetCLSID { 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } } - -#define guidOfficeIcon { 0xd309f794, 0x903f, 0x11d0, { 0x9e, 0xfc, 0x00, 0xa0, 0xc9, 0x11, 0x00, 0x4f } } -#define guidSHLMainMenu { 0xd309f791, 0x903f, 0x11d0, { 0x9e, 0xfc, 0x00, 0xa0, 0xc9, 0x11, 0x00, 0x4f } } - -#define guidSharedMenuGroup { 0x234a7fc1, 0xcfe9, 0x4335, { 0x9e, 0x82, 0x6, 0x1f, 0x86, 0xe4, 0x2, 0xc1 } } -#define guidStdEditor { 0x9ADF33D0, 0x8AAD, 0x11d0, { 0xB6, 0x06, 0x00, 0xA0, 0xC9, 0x22, 0xE8, 0x51 } } - -/////////////////////////////////////////////////////////////////////////////// -// Menu IDs - -#define IDM_VISUALD 0x0001 - -/////////////////////////////////////////////////////////////////////////////// -// Menu Group IDs - -#define IDG_VD_EDIT 0x0101 -#define IDG_VD_SEARCH 0x0100 -#define IDG_VD_BUILD 0x0102 -#define IDG_VD_WEB 0x0103 -#define IDG_VD_CONVERSION 0x0104 -#define IDG_VD_OUTLINE 0x0105 - -#define IDG_VS_MM_FILEEDITVIEW 0x0101 -#define IDG_VS_VIEW_BROWSER 0x0130 -#define IDG_VS_WNDO_FINDRESULTS 0x0724 -#define IDG_VS_EDIT_GOTO 0x012D -#define IDG_VS_EDIT_COMMANDWELL 0x012E -#define IDG_VS_PROJ_ADDREMOVE 0x0147 -#define IDG_VS_SOLNITEMS_PROJITEM 0x01BD -#define IDG_VS_CTXT_DELETE 0x022F -#define IDG_VS_EDIT_CUTCOPY 0x012A -#define IDG_VS_BUILD_MISC 0x0282 -#define IDG_VS_BUILD_CANCEL 0x0283 - -#define IDG_VS_EDITOR_OUTLINING_CMDS 0x3E90 -#define IDM_VS_EDITOR_OUTLINING_MENU 0x3EA1 -#define IDG_VS_CODEWIN_TEXTEDIT 0x01C0 -#define IDG_VS_CODEWIN_OUTLINING 0x02B3 - -/////////////////////////////////////////////////////////////////////////////// -// Bitmap IDs - -#define msotcidNoIcon 746 //(0,25) Label: '&No Icon' - -/////////////////////////////////////////////////////////////////////////////// - -CMDS_SECTION g_packageCLSID - - MENUS_BEGIN - // NewMenu Relative to Group Priority Type Name Text - g_packageCLSID:IDM_VISUALD, guidSHLMainMenu:IDG_VS_MM_FILEEDITVIEW, 0xF000, , "Visual D", "Visual D"; - MENUS_END - - NEWGROUPS_BEGIN - // NewGroup Parent Group Priority - g_packageCLSID:IDG_VD_SEARCH, g_packageCLSID:IDM_VISUALD, 0x0000; - g_packageCLSID:IDG_VD_EDIT, g_packageCLSID:IDM_VISUALD, 0x0001; - g_packageCLSID:IDG_VD_BUILD, g_packageCLSID:IDM_VISUALD, 0x0002; - g_packageCLSID:IDG_VD_CONVERSION, g_packageCLSID:IDM_VISUALD, 0x0003; - g_packageCLSID:IDG_VD_WEB, g_packageCLSID:IDM_VISUALD, 0x0004; - NEWGROUPS_END - - BUTTONS_BEGIN - // Command ID, Group ID, Priority, Icon ID, Button Type, Flags, Button Text, Menu Text, ToolTip Text, Command Well Text, English Command, Localized Command Name; - g_commandSetCLSID:CmdSearchSymbol, g_packageCLSID:IDG_VD_SEARCH, 0xF000, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Search Symbol", "Search S&ymbol", "Search Symbol in D Projects", , "SearchSymbol", "SearchSymbol"; - g_commandSetCLSID:CmdSearchFile, g_packageCLSID:IDG_VD_SEARCH, 0xF100, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Search File", "Search &File", "Search File in Solution", , "SearchFile", "SearchFile"; - g_commandSetCLSID:CmdReplaceTokens, g_packageCLSID:IDG_VD_SEARCH, 0xF100, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Search/Replace Tokens", "Search/&Replace Tokens...", "Search/Replace Tokens", , "SearchReplaceTokens", "SearchReplaceTokens"; - g_commandSetCLSID:CmdSearchTokNext, g_packageCLSID:IDG_VD_SEARCH, 0xF100, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Search Next Tokens", "Search &Next Tokens", "Search Next Tokens", , "SearchTokensNext", "SearchTokensNext"; - g_commandSetCLSID:CmdSearchTokPrev, g_packageCLSID:IDG_VD_SEARCH, 0xF100, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Search Previous Tokens", "Search Pre&vious Tokens", "Search Previous Tokens", , "SearchTokensPrev", "SearchTokensPrev"; - g_commandSetCLSID:CmdShowScope, g_packageCLSID:IDG_VD_EDIT, 0xF100, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Show Scope", "Show &Scope", "Show Scope of Cursor", , "ShowScope", "ShowScope"; - g_commandSetCLSID:CmdShowMethodTip, g_packageCLSID:IDG_VD_EDIT, 0xF200, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Show Parameter Info", "Show &Parameter Info", "Show Parameter Info", , "ParameterInfo", "ParameterInfo"; - g_commandSetCLSID:CmdToggleComment, g_packageCLSID:IDG_VD_EDIT, 0xF300, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Toggle Comment Selection", "Toggle &Comment Selection", "Toggle Comment Selection", , "ToggleCommentSelection", "ToggleCommentSelection"; - g_commandSetCLSID:CmdBuildPhobos, g_packageCLSID:IDG_VD_BUILD, 0xF300, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Build Phobos Browse Info", "Build Phobos &Browse Info", "Build Phobos Browse Info", , "BuildPhobosBrowseInfo", "BuildPhobosBrowseInfo"; - g_commandSetCLSID:CmdShowProfile, g_packageCLSID:IDG_VD_BUILD, 0xF300, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Open Profiler Window", "&Open Profiler Window", "Open Profiler Window", , "OpenProfilerWindow", "OpenProfilerWindow"; - g_commandSetCLSID:CmdCompileAndRun, g_packageCLSID:IDG_VD_BUILD, 0xF300, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Compile and Run", "Compile and Run", "Compile and Run", , "CompileAndRun", "CompileAndRun"; - g_commandSetCLSID:CmdCompileAndDbg, g_packageCLSID:IDG_VD_BUILD, 0xF300, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Compile and Debug", "Compile and Debug", "Compile and Debug", , "CompileAndDebug", "CompileAndDebug"; - g_commandSetCLSID:CmdCompileAndAsm, g_packageCLSID:IDG_VD_BUILD, 0xF300, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Compile and Disassemble", "Compile and Disassemble", "Compile and Disassemble", , "CompileAndDisasm", "CompileAndDisasm"; - g_commandSetCLSID:CmdDustMite, g_packageCLSID:IDG_VD_BUILD, 0xF300, guidOfficeIcon:msotcidNoIcon, BUTTON, , "DustMite", "DustMite Build Failure", "Reduce Failure with DustMite" , "DustMite", "DustMite"; - g_commandSetCLSID:CmdDelLstFiles, g_packageCLSID:IDG_VD_BUILD, 0xF301, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Delete Coverage Files", "Delete Coverage Files", "Delete Coverage Files", , "DeleteCoverageFiles", "DeleteCoverageFiles"; - g_commandSetCLSID:CmdConvWizard, g_packageCLSID:IDG_VD_CONVERSION, 0xF300, guidOfficeIcon:msotcidNoIcon, BUTTON, , "C++ Conversion Wizard", "C++ Conversion &Wizard...", "C++ Conversion Wizard", , "ConversionWizard", "ConversionWizard"; - g_commandSetCLSID:CmdConvSelection, g_packageCLSID:IDG_VD_CONVERSION, 0xF300, guidOfficeIcon:msotcidNoIcon, BUTTON, , "C++ Convert Selection", "C++ Convert Selection", "C++ Convert Selection", , "ConvertSelection", "ConvertSelection"; - g_commandSetCLSID:CmdShowLangPage, g_packageCLSID:IDG_VD_WEB, 0xF100, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Language Options", "Open Language &Options...", "Open Language Options", , "OpenLanguageOptions", "OpenLanguageOptions"; - g_commandSetCLSID:CmdShowWebsite, g_packageCLSID:IDG_VD_WEB, 0xF100, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Visual D Website", "Visual D &Website", "Open Visual D Website", , "OpenWebsite", "OpenWebsite"; - - //g_commandSetCLSID:CmdDeleteFile, guidSHLMainMenu:IDG_VS_EDIT_CUTCOPY, 0xF100, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Delete File", "Delete File", "Delete File", , "DeleteFile", "DeleteFile"; - g_commandSetCLSID:CmdCollapseUnittest, guidStdEditor:IDG_VS_EDITOR_OUTLINING_CMDS, 0xF100, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Collapse Unittests", "Collapse Unittests", "Collapse Unittests", , "CollapseUnittests", "CollapseUnittests"; - g_commandSetCLSID:CmdCollapseDisabled, guidStdEditor:IDG_VS_EDITOR_OUTLINING_CMDS, 0xF100, guidOfficeIcon:msotcidNoIcon, BUTTON, , "Collapse Disabled", "Collapse Disabled Code", "Collapse Disabled Code", , "CollapseDisabledCode", "CollapseDisabledCode"; - - // This icmdMyCommand is not defined as a shared command, so it uses our package CLSID - // as the command set GUID. Also, by specifying blank for the FLAGS, this command is - // default visible and enabled. Other valid values for FLAGS are the following: - // DEFAULTDISABLED, DEFAULTINVISIBLE, DYNAMICVISIBILITY, TEXTCHANGES - // These values for FLAGS can be or'ed together, e.g. "DEFAULTINVISIBLE | DYNAMICVISIBILITY" - - BUTTONS_END - - BITMAPS_BEGIN - // Bitmap Bitmap Index, Bitmap Index ... - BITMAPS_END - -CMDS_END - -CMDPLACEMENT_SECTION - // Command Group Priority - // g_commandSetCLSID:CmdDeleteFile, guidSharedMenuGroup:IDG_VS_EDIT_COMMANDWELL, 0xF100; -CMDPLACEMENT_END - -VISIBILITY_SECTION - // Command GUID when visible -VISIBILITY_END - -KEYBINDINGS_SECTION - // Command when available emulation keystate -KEYBINDINGS_END diff --git a/visuald/Resources/pkgcmd.cto b/visuald/Resources/pkgcmd.cto deleted file mode 100644 index 5aa36cfa..00000000 Binary files a/visuald/Resources/pkgcmd.cto and /dev/null differ diff --git a/visuald/Resources/pkgcmd.ctsym b/visuald/Resources/pkgcmd.ctsym deleted file mode 100644 index 1fcf00f2..00000000 --- a/visuald/Resources/pkgcmd.ctsym +++ /dev/null @@ -1,33 +0,0 @@ -"g_commandSetCLSID:CmdBuildPhobos"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x110 -"g_commandSetCLSID:CmdCollapseDisabled"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x121 -"g_commandSetCLSID:CmdCollapseUnittest"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x120 -"g_commandSetCLSID:CmdCompileAndAsm"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x118 -"g_commandSetCLSID:CmdCompileAndDbg"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x117 -"g_commandSetCLSID:CmdCompileAndRun"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x114 -"g_commandSetCLSID:CmdConvSelection"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x10a -"g_commandSetCLSID:CmdConvWizard"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x109 -"g_commandSetCLSID:CmdDelLstFiles"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x116 -"g_commandSetCLSID:CmdDustMite"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x119 -"g_commandSetCLSID:CmdReplaceTokens"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x106 -"g_commandSetCLSID:CmdSearchFile"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x102 -"g_commandSetCLSID:CmdSearchSymbol"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x101 -"g_commandSetCLSID:CmdSearchTokNext"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x107 -"g_commandSetCLSID:CmdSearchTokPrev"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x108 -"g_commandSetCLSID:CmdShowLangPage"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x115 -"g_commandSetCLSID:CmdShowMethodTip"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x104 -"g_commandSetCLSID:CmdShowProfile"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x111 -"g_commandSetCLSID:CmdShowScope"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x103 -"g_commandSetCLSID:CmdShowWebsite"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x112 -"g_commandSetCLSID:CmdToggleComment"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x03, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x105 -"g_packageCLSID"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x7f, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } } -"g_packageCLSID:IDG_VD_BUILD"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x7f, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x0102 -"g_packageCLSID:IDG_VD_CONVERSION"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x7f, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x0104 -"g_packageCLSID:IDG_VD_EDIT"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x7f, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x0101 -"g_packageCLSID:IDG_VD_SEARCH"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x7f, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x0100 -"g_packageCLSID:IDG_VD_WEB"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x7f, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x0103 -"g_packageCLSID:IDM_VISUALD"={ 0x002a2de9, 0x8bb6, 0x484d, { 0x98, 0x7f, 0x7e, 0x4a, 0xd4, 0x08, 0x47, 0x15 } }:0x0001 -"guidOfficeIcon:msotcidNoIcon"={ 0xd309f794, 0x903f, 0x11d0, { 0x9e, 0xfc, 0x00, 0xa0, 0xc9, 0x11, 0x00, 0x4f } }:746 -"guidSHLMainMenu:IDG_VS_MM_FILEEDITVIEW"={ 0xd309f791, 0x903f, 0x11d0, { 0x9e, 0xfc, 0x00, 0xa0, 0xc9, 0x11, 0x00, 0x4f } }:0x0101 -"guidStdEditor:IDG_VS_EDITOR_OUTLINING_CMDS"={ 0x9ADF33D0, 0x8AAD, 0x11d0, { 0xB6, 0x06, 0x00, 0xA0, 0xC9, 0x22, 0xE8, 0x51 } }:0x3E90 - - diff --git a/visuald/Resources/pkgcmd.vsct b/visuald/Resources/pkgcmd.vsct new file mode 100644 index 00000000..3df689e1 --- /dev/null +++ b/visuald/Resources/pkgcmd.vsct @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + + Visual D + Visual D + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/visuald/Resources/resources.h b/visuald/Resources/resources.h index f29322e8..8d8f56ef 100644 --- a/visuald/Resources/resources.h +++ b/visuald/Resources/resources.h @@ -6,6 +6,8 @@ #define ICON_ABOUTBOX 1000 #define BMP_SPLASHSCRN 1001 +#define BMP_DIMAGELIST 1002 +#define BMP_COMPLETION 1003 #define IDI_ASCENDING 2000 #define IDI_DESCENDING 2001 @@ -55,3 +57,6 @@ #define CmdCollapseUnittest 0x120 #define CmdCollapseDisabled 0x121 + +#define CmdNewPackage 0x122 +#define CmdNewFilter 0x123 diff --git a/visuald/automation.d b/visuald/automation.d index 54e92e4d..330d4115 100644 --- a/visuald/automation.d +++ b/visuald/automation.d @@ -15,6 +15,7 @@ import stdext.path; import sdk.vsi.vsshell; import sdk.vsi.vsshell80; +import sdk.vsi.vslangproj : prjOutputTypeWinExe; import dte = sdk.vsi.dte80a; import visuald.comutil; @@ -49,21 +50,21 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem } /+[id(0x0000000a), propget, hidden, helpstring("Returns value indicating whether object was changed since the last time it was saved."), helpcontext(0x0000eadb)]+/ - override HRESULT IsDirty(/+[out, retval]+/ VARIANT_BOOL* lpfReturn) + override HRESULT get_IsDirty(/+[out, retval]+/ VARIANT_BOOL* lpfReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x0000000a), propput, hidden, helpstring("Returns value indicating whether object was changed since the last time it was saved."), helpcontext(0x0000eadb)]+/ - override HRESULT IsDirty(in VARIANT_BOOL lpfReturn) + override HRESULT put_IsDirty(in VARIANT_BOOL lpfReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x0000000b), propget, helpstring("Returns the full pathnames of the files associated with a project item."), helpcontext(0x0000eac9)]+/ - override HRESULT FileNames(in short index, + override HRESULT get_FileNames(in short index, /+[out, retval]+/ BSTR* lpbstrReturn) { mixin(LogCallMix); @@ -72,7 +73,7 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem } /+[id(0x0000000c), helpstring("Saves the project."), helpcontext(0x0000ea8f)]+/ - override HRESULT SaveAs(in BSTR NewFileName, + override HRESULT SaveAs(in BSTR NewFileName, /+[out, retval]+/ VARIANT_BOOL* lpfReturn) { mixin(LogCallMix); @@ -80,14 +81,14 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem } /+[id(0x0000000d), propget, helpstring("Returns the number of files associated with the project item."), helpcontext(0x0000eac4)]+/ - override HRESULT FileCount(/+[out, retval]+/ short* lpsReturn) + override HRESULT get_FileCount(/+[out, retval]+/ short* lpsReturn) { *lpsReturn = 1; return S_OK; } /+[id(00000000), propget, helpstring("Sets/returns the name of the project."), helpcontext(0x0000eae9)]+/ - override HRESULT Name(/+[out, retval]+/ BSTR* pbstrReturn) + override HRESULT get_Name(/+[out, retval]+/ BSTR* pbstrReturn) { mixin(LogCallMix); *pbstrReturn = allocBSTR(mNode.GetDisplayCaption()); @@ -95,14 +96,14 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem } /+[id(00000000), propput, helpstring("Sets/returns the name of the project."), helpcontext(0x0000eae9)]+/ - override HRESULT Name(in BSTR pbstrReturn) + override HRESULT put_Name(in BSTR pbstrReturn) { mixin(LogCallMix); return S_FALSE; } /+[id(0x00000036), propget, helpstring("Returns the collection containing the object supporting this property."), helpcontext(0x0000eab1)]+/ - override HRESULT Collection(/+[out, retval]+/ dte.ProjectItems * lppcReturn) + override HRESULT get_Collection(/+[out, retval]+/ dte.ProjectItems * lppcReturn) { mixin(LogCallMix); *lppcReturn = addref(mParent); @@ -110,35 +111,35 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem } /+[id(0x00000038), propget, helpstring("Returns the Properties collection."), helpcontext(0x0000eaf9)]+/ - override HRESULT Properties(/+[out, retval]+/ dte.Properties * ppObject) + override HRESULT get_Properties(/+[out, retval]+/ dte.Properties * ppObject) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x000000c8), propget, helpstring("Returns the top-level extensibility object."), helpcontext(0x0000eac1)]+/ - override HRESULT DTE(/+[out, retval]+/ dte.DTE * lppaReturn) + override HRESULT get_DTE(/+[out, retval]+/ dte.DTE * lppaReturn) { logCall("%s.get_DTE()", this); return GetDTE(lppaReturn); } - /+[id(0x000000c9), propget, helpstring("Returns a GUID String indicating the kind or type of the object."), helpcontext(0x0000eadd)]+/ - override HRESULT Kind(/+[out, retval]+/ BSTR* lpbstrFileName) + /+[id(0x000000c9), get_propget, helpstring("Returns a GUID String indicating the kind or type of the object."), helpcontext(0x0000eadd)]+/ + override HRESULT get_Kind(/+[out, retval]+/ BSTR* lpbstrFileName) { mixin(LogCallMix); return returnError(E_NOTIMPL); } - /+[id(0x000000cb), propget, helpstring("Returns a ProjectItems collection for the object."), helpcontext(0x0000eaf6)]+/ - override HRESULT ProjectItems(/+[out, retval]+/ dte.ProjectItems * lppcReturn) + /+[id(0x000000cb), get_propget, helpstring("Returns a ProjectItems collection for the object."), helpcontext(0x0000eaf6)]+/ + override HRESULT get_ProjectItems(/+[out, retval]+/ dte.ProjectItems * lppcReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x000000cc), propget, helpstring("Returns value indicating whether the ProjectItem is open for a particular view."), helpcontext(0x0000eadc)]+/ - override HRESULT IsOpen(/+[ optional , defaultvalue("{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}")]+/ in BSTR ViewKind, + override HRESULT get_IsOpen(/+[ optional , defaultvalue("{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}")]+/ in BSTR ViewKind, /+[out, retval]+/ VARIANT_BOOL* lpfReturn) { mixin(LogCallMix); @@ -146,7 +147,7 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem } /+[id(0x000000cd), helpstring("Opens the ProjectItem object in the specified view."), helpcontext(0x0000ea88)]+/ - override HRESULT Open(/+[ optional , defaultvalue("{00000000-0000-0000-0000-000000000000}")]+/ in BSTR ViewKind, + override HRESULT Open(/+[ optional , defaultvalue("{00000000-0000-0000-0000-000000000000}")]+/ in BSTR ViewKind, /+[out, retval]+/ dte.Window * lppfReturn) { mixin(LogCallMix); @@ -168,7 +169,7 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem } /+[id(0x0000006c), propget, helpstring("Returns an interface or object that can be accessed at run time by name."), helpcontext(0x0000ea7f)]+/ - override HRESULT Object(/+[out, retval]+/ IDispatch * ProjectItemModel) + override HRESULT get_Object(/+[out, retval]+/ IDispatch * ProjectItemModel) { mixin(LogCallMix); *ProjectItemModel = addref(this); @@ -176,7 +177,7 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem } /+[id(0x0000006d), propget, helpstring("Get an Extender for this object under the specified category."), helpcontext(0x0000eb84)]+/ - override HRESULT Extender(in BSTR ExtenderName, + override HRESULT get_Extender(in BSTR ExtenderName, /+[out, retval]+/ IDispatch * Extender) { mixin(LogCallMix); @@ -184,42 +185,42 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem } /+[id(0x0000006e), propget, helpstring("Get a list of available Extenders on this object."), helpcontext(0x0000eb85)]+/ - override HRESULT ExtenderNames(/+[out, retval]+/ VARIANT* ExtenderNames) + override HRESULT get_ExtenderNames(/+[out, retval]+/ VARIANT* ExtenderNames) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x0000006f), propget, helpstring("Get the Extension Category ID of this object."), helpcontext(0x0000eb86)]+/ - override HRESULT ExtenderCATID(/+[out, retval]+/ BSTR* pRetval) + override HRESULT get_ExtenderCATID(/+[out, retval]+/ BSTR* pRetval) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000071), propget, helpstring("Returns value indicating whether object was changed since the last time it was saved."), helpcontext(0x0000eadb)]+/ - override HRESULT Saved(/+[out, retval]+/ VARIANT_BOOL* lpfReturn) + override HRESULT get_Saved(/+[out, retval]+/ VARIANT_BOOL* lpfReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000071), propput, helpstring("Returns value indicating whether object was changed since the last time it was saved."), helpcontext(0x0000eadb)]+/ - override HRESULT Saved(in VARIANT_BOOL lpfReturn) + override HRESULT put_Saved(in VARIANT_BOOL lpfReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000074), propget, helpstring("Returns the ConfigurationManager object for this item."), helpcontext(0x0000ece9)]+/ - override HRESULT ConfigurationManager(/+[out, retval]+/ dte.ConfigurationManager * ppConfigurationManager) + override HRESULT get_ConfigurationManager(/+[out, retval]+/ dte.ConfigurationManager * ppConfigurationManager) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000075), propget, helpstring("Returns the CodeModel object for this item."), helpcontext(0x0000ecea)]+/ - override HRESULT FileCodeModel(/+[out, retval]+/ dte.FileCodeModel * ppFileCodeModel) + override HRESULT get_FileCodeModel(/+[out, retval]+/ dte.FileCodeModel * ppFileCodeModel) { mixin(LogCallMix); return returnError(E_NOTIMPL); @@ -233,24 +234,25 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem } /+[id(0x00000077), propget, helpstring("Returns the Document object for this item."), helpcontext(0x0000ecfc)]+/ - override HRESULT Document(/+[out, retval]+/ dte.Document * ppDocument) + override HRESULT get_Document(/+[out, retval]+/ dte.Document * ppDocument) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000078), propget, helpstring("If the project item is the root of a sub-project, then returns the Project object for the sub-project."), helpcontext(0x0000ecfd)]+/ - override HRESULT SubProject(/+[out, retval]+/ dte.Project * ppProject) + override HRESULT get_SubProject(/+[out, retval]+/ dte.Project * ppProject) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000079), propget, helpstring("Returns the project that hosts this ProjectItem object."), helpcontext(0x0000ed1b)]+/ - override HRESULT ContainingProject(/+[out, retval]+/ dte.Project * ppProject) + override HRESULT get_ContainingProject(/+[out, retval]+/ dte.Project * ppProject) { mixin(LogCallMix); - return returnError(E_NOTIMPL); + *ppProject = addref(mExtProject); + return S_OK; } /+[id(0x0000007a), helpstring("Removes the item from the project and it's storage."), helpcontext(0x0000ecfe)]+/ @@ -264,9 +266,9 @@ class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem __gshared ComTypeInfoHolder mTypeHolder; static void shared_static_this_typeHolder() { - static class _ComTypeInfoHolder : ComTypeInfoHolder + static class _ComTypeInfoHolder : ComTypeInfoHolder { - override int GetIDsOfNames( + override int GetIDsOfNames( /* [size_is][in] */ in LPOLESTR *rgszNames, /* [in] */ in UINT cNames, /* [size_is][out] */ MEMBERID *pMemId) @@ -455,7 +457,7 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems __gshared ComTypeInfoHolder mTypeHolder; override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } - + override void Dispose() { } @@ -469,7 +471,7 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems return super.QueryInterface(riid, pvObject); } - override int Item( + override int Item( /* [in] */ in VARIANT index, /* [retval][out] */ dte.ProjectItem *lppcReturn) { @@ -477,7 +479,7 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems return returnError(E_NOTIMPL); } - override int Parent( + override int get_Parent( /* [retval][out] */ IDispatch* lppptReturn) { mixin(LogCallMix); @@ -485,7 +487,7 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems return S_OK; } - override int Count( + override int get_Count( /* [retval][out] */ int *lplReturn) { logCall("%s.get_Count(lplReturn=%s)", this, lplReturn); @@ -498,7 +500,7 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems return S_OK; } - override int _NewEnum( + override int _NewEnum( /* [retval][out] */ IUnknown *lppiuReturn) { mixin(LogCallMix); @@ -511,21 +513,21 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems return S_OK; } - override int DTE( + override int get_DTE( /* [retval][out] */ dte.DTE *lppaReturn) { logCall("%s.get_DTE()", this); return GetDTE(lppaReturn); } - override int Kind( + override int get_Kind( /* [retval][out] */ BSTR *lpbstrFileName) { logCall("%s.get_Kind(lpbstrFileName=%s)", this, lpbstrFileName); return returnError(E_NOTIMPL); } - override int AddFromFile( + override int AddFromFile( /* [in] */ in BSTR FileName, /* [retval][out] */ dte.ProjectItem *lppcReturn) { @@ -533,7 +535,7 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems return returnError(E_NOTIMPL); } - override int AddFromTemplate( + override int AddFromTemplate( /* [in] */ in BSTR FileName, /* [in] */ in BSTR Name, /* [retval][out] */ dte.ProjectItem *lppcReturn) @@ -542,7 +544,7 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems return returnError(E_NOTIMPL); } - override int AddFromDirectory( + override int AddFromDirectory( /* [in] */ in BSTR Directory, /* [retval][out] */ dte.ProjectItem *lppcReturn) { @@ -550,7 +552,7 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems return returnError(E_NOTIMPL); } - override int ContainingProject( + override int get_ContainingProject( /* [retval][out] */ dte.Project* ppProject) { mixin(LogCallMix); @@ -558,7 +560,7 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems return S_OK; } - override int AddFolder( + override int AddFolder( BSTR Name, /* [defaultvalue] */ BSTR Kind, /* [retval][out] */ dte.ProjectItem *pProjectItem) @@ -567,7 +569,7 @@ class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems return returnError(E_NOTIMPL); } - override int AddFromFileCopy( + override int AddFromFileCopy( BSTR FilePath, /* [retval][out] */ dte.ProjectItem *pProjectItem) { @@ -626,32 +628,32 @@ class ExtProperties : DisposingDispatchObject, dte.Properties if(prop == "FullPath") { string fullpath = mProject.mProject.GetFilename(); - *lplppReturn = addref(newCom!ExtProperty(this, prop, fullpath)); + *lplppReturn = addref(newCom!(ExtProperty!string)(this, prop, fullpath)); return S_OK; } if(prop == "ProjectDirectory") { string fullpath = dirName(mProject.mProject.GetFilename()); - *lplppReturn = addref(newCom!ExtProperty(this, prop, fullpath)); + *lplppReturn = addref(newCom!(ExtProperty!string)(this, prop, fullpath)); return S_OK; } return returnError(S_FALSE); } /+[id(0x00000001), propget, restricted, hidden]+/ - override HRESULT Application(/+[out, retval]+/ IDispatch * lppidReturn) + override HRESULT get_Application(/+[out, retval]+/ IDispatch * lppidReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000002), propget, helpstring("Returns the parent object."), helpcontext(0x0000eaf2)]+/ - override HRESULT Parent(/+[out, retval]+/ IDispatch * lppidReturn) + override HRESULT get_Parent(/+[out, retval]+/ IDispatch * lppidReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000028), propget, helpstring("Returns value indicating the count of objects in the collection."), helpcontext(0x0000eabb)]+/ - override HRESULT Count(/+[out, retval]+/ int* lplReturn) + override HRESULT get_Count(/+[out, retval]+/ int* lplReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); @@ -663,7 +665,7 @@ class ExtProperties : DisposingDispatchObject, dte.Properties return returnError(E_NOTIMPL); } /+[id(0x00000064), propget, helpstring("Returns the top-level extensibility object."), helpcontext(0x0000eac1)]+/ - override HRESULT DTE(/+[out, retval]+/ dte.DTE * lppaReturn) + override HRESULT get_DTE(/+[out, retval]+/ dte.DTE * lppaReturn) { logCall("%s.get_DTE()", this); return GetDTE(lppaReturn); @@ -673,9 +675,9 @@ class ExtProperties : DisposingDispatchObject, dte.Properties __gshared ComTypeInfoHolder mTypeHolder; static void shared_static_this_typeHolder() { - static class _ComTypeInfoHolder : ComTypeInfoHolder + static class _ComTypeInfoHolder : ComTypeInfoHolder { - override int GetIDsOfNames( + override int GetIDsOfNames( /* [size_is][in] */ in LPOLESTR *rgszNames, /* [in] */ in UINT cNames, /* [size_is][out] */ MEMBERID *pMemId) @@ -703,9 +705,9 @@ private: ExtProject mProject; } -class ExtProperty : DisposingDispatchObject, dte.Property +class ExtProperty(T) : DisposingDispatchObject, dte.Property { - this(ExtProperties props, string name, string value) + this(ExtProperties props, string name, T value) { mProperties = addref(props); mName = name; @@ -726,33 +728,43 @@ class ExtProperty : DisposingDispatchObject, dte.Property return super.QueryInterface(riid, pvObject); } - HRESULT Value(/+[out, retval]+/ VARIANT* lppvReturn) + override HRESULT get_Value(/+[out, retval]+/ VARIANT* lppvReturn) { mixin(LogCallMix); - lppvReturn.vt = VT_BSTR; - lppvReturn.bstrVal = allocBSTR(mValue); + static if(is (T == string)) + { + lppvReturn.vt = VT_BSTR; + lppvReturn.bstrVal = allocBSTR(mValue); + } + else static if (is(T == int)) + { + lppvReturn.vt = VT_INT; + lppvReturn.intVal = mValue; + } + else + static assert(false, "unsupported type in ExtProperty.Value"); return S_OK; } /+[id(00000000), propput, helpstring("Sets/ returns the value of property returned by the Property object."), helpcontext(0x0000eb08)]+/ - HRESULT Value(in VARIANT lppvReturn) + override HRESULT put_Value(in VARIANT lppvSet) { mixin(LogCallMix); return returnError(S_FALSE); } /+[id(00000000), propputref, helpstring("Sets/ returns the value of property returned by the Property object."), helpcontext(0x0000eb08)]+/ - HRESULT putref_Value(in VARIANT lppvReturn) + override HRESULT putref_Value(in VARIANT lppvReturn) { mixin(LogCallMix); return returnError(S_FALSE); } /+[id(0x00000003), propget, helpstring("Returns one element of a list."), helpcontext(0x0000ead6)]+/ - HRESULT IndexedValue(in VARIANT Index1, - /+[ optional]+/ in VARIANT Index2, - /+[ optional]+/ in VARIANT Index3, - /+[ optional]+/ in VARIANT Index4, + override HRESULT get_IndexedValue(in VARIANT Index1, + /+[ optional]+/ in VARIANT Index2, + /+[ optional]+/ in VARIANT Index3, + /+[ optional]+/ in VARIANT Index4, /+[out, retval]+/ VARIANT* Val) { mixin(LogCallMix); @@ -760,10 +772,10 @@ class ExtProperty : DisposingDispatchObject, dte.Property } /+[id(0x00000003), propput, helpstring("Returns one element of a list."), helpcontext(0x0000ead6)]+/ - HRESULT IndexedValue(in VARIANT Index1, - /+[ optional]+/ in VARIANT Index2, - /+[ optional]+/ in VARIANT Index3, - /+[ optional]+/ in VARIANT Index4, + override HRESULT put_IndexedValue(in VARIANT Index1, + /+[ optional]+/ in VARIANT Index2, + /+[ optional]+/ in VARIANT Index3, + /+[ optional]+/ in VARIANT Index4, in VARIANT Val) { mixin(LogCallMix); @@ -771,21 +783,21 @@ class ExtProperty : DisposingDispatchObject, dte.Property } /+[id(0x00000004), propget, helpstring("Returns a value representing the number of items in the list value."), helpcontext(0x0000eaea)]+/ - HRESULT NumIndices(/+[out, retval]+/ short* lpiRetVal) + override HRESULT get_NumIndices(/+[out, retval]+/ short* lpiRetVal) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000001), propget, restricted, hidden]+/ - HRESULT Application(/+[out, retval]+/ IDispatch * lppidReturn) + override HRESULT get_Application(/+[out, retval]+/ IDispatch * lppidReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000002), propget, restricted, hidden]+/ - HRESULT Parent(/+[out, retval]+/ dte.Properties * lpppReturn) + override HRESULT get_Parent(/+[out, retval]+/ dte.Properties * lpppReturn) { mixin(LogCallMix); *lpppReturn = addref(mProperties); @@ -793,7 +805,7 @@ class ExtProperty : DisposingDispatchObject, dte.Property } /+[id(0x00000028), propget, helpstring("Returns the name of the object."), helpcontext(0x0000edbb)]+/ - HRESULT Name(/+[out, retval]+/ BSTR* lpbstrReturn) + override HRESULT get_Name(/+[out, retval]+/ BSTR* lpbstrReturn) { mixin(LogCallMix); *lpbstrReturn = allocBSTR(mName); @@ -801,7 +813,7 @@ class ExtProperty : DisposingDispatchObject, dte.Property } /+[id(0x0000002a), propget, helpstring("Returns the collection containing the object supporting this property."), helpcontext(0x0000eab1)]+/ - HRESULT Collection(/+[out, retval]+/ dte.Properties * lpppReturn) + override HRESULT get_Collection(/+[out, retval]+/ dte.Properties * lpppReturn) { mixin(LogCallMix); *lpppReturn = addref(mProperties); @@ -809,21 +821,21 @@ class ExtProperty : DisposingDispatchObject, dte.Property } /+[id(0x0000002d), propget, helpstring("Sets/returns value of Property object when type of value is Object."), helpcontext(0x0000eaed)]+/ - HRESULT Object(/+[out, retval]+/ IDispatch * lppunk) + override HRESULT get_Object(/+[out, retval]+/ IDispatch * lppunk) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x0000002d), propputref, helpstring("Sets/returns value of Property object when type of value is Object."), helpcontext(0x0000eaed)]+/ - HRESULT Object(/+[in]+/ IUnknown lppunk) + override HRESULT putref_Object(/+[in]+/ IUnknown lppunk) { mixin(LogCallMix); return returnError(E_NOTIMPL); } /+[id(0x00000064), propget, helpstring("Returns the top-level extensibility object."), helpcontext(0x0000eac1)]+/ - HRESULT DTE(/+[out, retval]+/ dte.DTE * lppaReturn) + override HRESULT get_DTE(/+[out, retval]+/ dte.DTE * lppaReturn) { logCall("%s.get_DTE()", this); return GetDTE(lppaReturn); @@ -834,9 +846,9 @@ class ExtProperty : DisposingDispatchObject, dte.Property __gshared ComTypeInfoHolder mTypeHolder; static void shared_static_this_typeHolder() { - static class _ComTypeInfoHolder : ComTypeInfoHolder + static class _ComTypeInfoHolder : ComTypeInfoHolder { - override int GetIDsOfNames( + override int GetIDsOfNames( /* [size_is][in] */ in LPOLESTR *rgszNames, /* [in] */ in UINT cNames, /* [size_is][out] */ MEMBERID *pMemId) @@ -862,7 +874,7 @@ class ExtProperty : DisposingDispatchObject, dte.Property private: string mName; - string mValue; + T mValue; ExtProperties mProperties; } @@ -890,7 +902,7 @@ class ExtProject : ExtProjectItem, dte.Project } // DTE.Project - override int Name( + override int get_Name( /* [retval][out] */ BSTR *lpbstrName) { logCall("%s.get_Name(lpbstrName=%s)", this, _toLog(lpbstrName)); @@ -898,7 +910,7 @@ class ExtProject : ExtProjectItem, dte.Project return S_OK; } - override int Name( + override int put_Name( /* [in] */ in BSTR bstrName) { logCall("%s.put_Name(bstrName=%s)", this, _toLog(bstrName)); @@ -906,7 +918,7 @@ class ExtProject : ExtProjectItem, dte.Project return S_OK; } - override int FileName( + override int get_FileName( /* [retval][out] */ BSTR *lpbstrName) { logCall("%s.get_FileName(lpbstrName=%s)", this, _toLog(lpbstrName)); @@ -914,21 +926,21 @@ class ExtProject : ExtProjectItem, dte.Project return S_OK; } - override int IsDirty( + override int get_IsDirty( /* [retval][out] */ VARIANT_BOOL *lpfReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); } - override int IsDirty( + override int put_IsDirty( /* [in] */ in VARIANT_BOOL Dirty) { logCall("%s.put_IsDirty(Dirty=%s)", this, _toLog(Dirty)); return returnError(E_NOTIMPL); } - override int Collection( + override int get_Collection( /* [retval][out] */ dte.Projects *lppaReturn) { mixin(LogCallMix); @@ -938,7 +950,7 @@ class ExtProject : ExtProjectItem, dte.Project scope(exit) release(_dte); IUnknown solution; // dte.Solution not derived from IUnknown?! - if(_dte.Solution(cast(dte.Solution*)&solution) != S_OK || !solution) + if(_dte.get_Solution(cast(dte.Solution*)&solution) != S_OK || !solution) return returnError(E_FAIL); scope(exit) release(solution); @@ -947,24 +959,24 @@ class ExtProject : ExtProjectItem, dte.Project return returnError(E_FAIL); scope(exit) release(_solution); - return _solution.Projects(lppaReturn); + return _solution.get_Projects(lppaReturn); } - override int SaveAs( + override int SaveAs( /* [in] */ in BSTR NewFileName) { logCall("%s.SaveAs(NewFileName=%s)", this, _toLog(NewFileName)); return returnError(E_NOTIMPL); } - override int DTE( + override int get_DTE( /* [retval][out] */ dte.DTE *lppaReturn) { logCall("%s.get_DTE()", this); return GetDTE(lppaReturn); } - override int Kind( + override int get_Kind( /* [retval][out] */ BSTR *lpbstrName) { logCall("%s.get_Kind(lpbstrName=%s)", this, _toLog(lpbstrName)); @@ -973,7 +985,7 @@ class ExtProject : ExtProjectItem, dte.Project return S_OK; } - override int ProjectItems( + override int get_ProjectItems( /* [retval][out] */ dte.ProjectItems* lppcReturn) { mixin(LogCallMix); @@ -981,7 +993,7 @@ class ExtProject : ExtProjectItem, dte.Project return S_OK; } - override int Properties( + override int get_Properties( /* [retval][out] */ dte.Properties *ppObject) { mixin(LogCallMix); @@ -989,7 +1001,7 @@ class ExtProject : ExtProjectItem, dte.Project return S_OK; } - override int UniqueName( + override int get_UniqueName( /* [retval][out] */ BSTR *lpbstrName) { logCall("%s.get_UniqueName(lpbstrName=%s)", this, _toLog(lpbstrName)); @@ -1002,14 +1014,14 @@ class ExtProject : ExtProjectItem, dte.Project return returnError(E_FAIL); IVsHierarchy pIVsHierarchy = mProject; // ->GetIVsHierarchy(); - + int hr = srpSolution.GetUniqueNameOfProject(pIVsHierarchy, lpbstrName); srpSolution.Release(); return hr; } - override int Object( + override int get_Object( /* [retval][out] */ IDispatch* ProjectModel) { logCall("%s.get_Object(out ProjectModel=%s)", this, _toLog(&ProjectModel)); @@ -1017,7 +1029,7 @@ class ExtProject : ExtProjectItem, dte.Project return S_OK; } - override int Extender( + override int get_Extender( /* [in] */ in BSTR ExtenderName, /* [retval][out] */ IDispatch *Extender) { @@ -1025,42 +1037,42 @@ class ExtProject : ExtProjectItem, dte.Project return returnError(E_NOTIMPL); } - override int ExtenderNames( + override int get_ExtenderNames( /* [retval][out] */ VARIANT *ExtenderNames) { logCall("%s.get_ExtenderNames(ExtenderNames=%s)", this, _toLog(ExtenderNames)); return returnError(E_NOTIMPL); } - override int ExtenderCATID( + override int get_ExtenderCATID( /* [retval][out] */ BSTR *pRetval) { logCall("%s.get_ExtenderCATID(pRetval=%s)", this, _toLog(pRetval)); return returnError(E_NOTIMPL); } - override int FullName( + override int get_FullName( /* [retval][out] */ BSTR *lpbstrName) { logCall("%s.get_FullName(lpbstrName=%s)", this, _toLog(lpbstrName)); - return FileName(lpbstrName); + return get_FileName(lpbstrName); } - override int Saved( + override int get_Saved( /* [retval][out] */ VARIANT_BOOL *lpfReturn) { mixin(LogCallMix); return returnError(E_NOTIMPL); } - override int Saved( + override int put_Saved( /* [in] */ in VARIANT_BOOL SavedFlag) { logCall("put_Saved(SavedFlag=%s)", _toLog(SavedFlag)); return returnError(E_NOTIMPL); } - override int ConfigurationManager( + override int get_ConfigurationManager( /* [retval][out] */ dte.ConfigurationManager* ppConfigurationManager) { mixin(LogCallMix); @@ -1069,7 +1081,7 @@ class ExtProject : ExtProjectItem, dte.Project return S_OK; } - override int Globals( + override int get_Globals( /* [retval][out] */ dte.Globals* ppGlobals) { mixin(LogCallMix); @@ -1100,21 +1112,108 @@ class ExtProject : ExtProjectItem, dte.Project return hr; } - override int Save( + override int Save( /* [defaultvalue] */ BSTR FileName) { logCall("Save(FileName=%s)", _toLog(FileName)); return returnError(E_NOTIMPL); } - override int ParentProjectItem( + /////////////////////////////////////////// + extern(D) + static bool searchNestedHierarchy(IVsHierarchy pHierarchy, VSITEMID item, + scope bool delegate (IVsHierarchy, VSITEMID, IVsHierarchy, VSITEMID) dg) + { + VARIANT var; + if((pHierarchy.GetProperty(item, VSHPROPID_Container, &var) == S_OK && + ((var.vt == VT_BOOL && var.boolVal) || (var.vt == VT_I4 && var.lVal))) || + (pHierarchy.GetProperty(item, VSHPROPID_Expandable, &var) == S_OK && + ((var.vt == VT_BOOL && var.boolVal) || (var.vt == VT_I4 && var.lVal)))) + { + IVsHierarchy nestedHierarchy; + VSITEMID itemidNested; + if(pHierarchy.GetNestedHierarchy(item, &IVsHierarchy.iid, cast(void **)&nestedHierarchy, &itemidNested) == S_OK) + { + scope(exit) release(nestedHierarchy); + if(dg(pHierarchy, item, nestedHierarchy, itemidNested)) + return true; + if(searchNestedHierarchy(nestedHierarchy, itemidNested, dg)) + return true; + } + else if(pHierarchy.GetProperty(item, VSHPROPID_FirstChild, &var) == S_OK && + (var.vt == VT_INT_PTR || var.vt == VT_I4 || var.vt == VT_INT)) + { + VSITEMID chid = var.lVal; + while(chid != VSITEMID_NIL) + { + VARIANT name; + pHierarchy.GetProperty(item, VSHPROPID_Name, &name); + detachBSTR(name.bstrVal); + + if(searchNestedHierarchy(pHierarchy, chid, dg)) + return true; + + if(pHierarchy.GetProperty(chid, VSHPROPID_NextSibling, &var) != S_OK || + (var.vt != VT_INT_PTR && var.vt != VT_I4 && var.vt != VT_INT)) + break; + chid = var.lVal; + } + } + } + + return false; + } + + override int get_ParentProjectItem( /* [retval][out] */ dte.ProjectItem *ppParentProjectItem) { mixin(LogCallMix); - return returnError(E_NOTIMPL); + + IVsSolution srpSolution = queryService!(IVsSolution); + if(!srpSolution) + return returnError(E_FAIL); + + *ppParentProjectItem = null; + int hr = E_UNEXPECTED; + + IVsHierarchy pIVsHierarchy = mProject; // ->GetIVsHierarchy(); + auto hierSolution = qi_cast!(IVsHierarchy)(srpSolution); + if (hierSolution) + { + IVsHierarchy parentHier; + VSITEMID parentItem; + bool matchItem(IVsHierarchy hier, VSITEMID item, IVsHierarchy nestedHier, VSITEMID nestItem) + { + if (nestedHier == pIVsHierarchy) + { + parentHier = addref(hier); + parentItem = item; + return true; + } + return false; + } + + if (searchNestedHierarchy(hierSolution, VSITEMID_ROOT, &matchItem)) + { + VARIANT var; + hr = parentHier.GetProperty(VSITEMID_ROOT, VSHPROPID_ExtObject, &var); + if (hr == S_OK && var.vt == VT_DISPATCH && var.pdispVal) + { + *ppParentProjectItem = qi_cast!(dte.ProjectItem)(var.pdispVal); + release(var.pdispVal); + } + else if (hr == S_OK) + hr = E_UNEXPECTED; + } + release(parentHier); + release(hierSolution); + } + release(srpSolution); + + return hr; } - override int CodeModel( + override int get_CodeModel( /* [retval][out] */ dte.CodeModel *ppCodeModel) { mixin(LogCallMix); @@ -1133,9 +1232,9 @@ class ExtProject : ExtProjectItem, dte.Project __gshared ComTypeInfoHolder mTypeHolder; static void shared_static_this_typeHolder() { - static class _ComTypeInfoHolder : ComTypeInfoHolder + static class _ComTypeInfoHolder : ComTypeInfoHolder { - override int GetIDsOfNames( + override int GetIDsOfNames( /* [size_is][in] */ in LPOLESTR *rgszNames, /* [in] */ in UINT cNames, /* [size_is][out] */ MEMBERID *pMemId) @@ -1158,7 +1257,7 @@ class ExtProject : ExtProjectItem, dte.Project } override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } - + Project mProject; dte.Properties mProperties; } @@ -1167,7 +1266,8 @@ void automation_shared_static_this_typeHolder() { ExtProjectItem.shared_static_this_typeHolder(); ExtProperties.shared_static_this_typeHolder(); - ExtProperty.shared_static_this_typeHolder(); + ExtProperty!string.shared_static_this_typeHolder(); + ExtProperty!int.shared_static_this_typeHolder(); ExtProject.shared_static_this_typeHolder(); } @@ -1175,6 +1275,7 @@ void automation_shared_static_dtor_typeHolder() { ExtProjectItem.shared_static_dtor_typeHolder(); ExtProperties.shared_static_dtor_typeHolder(); - ExtProperty.shared_static_dtor_typeHolder(); + ExtProperty!string.shared_static_dtor_typeHolder(); + ExtProperty!int.shared_static_dtor_typeHolder(); ExtProject.shared_static_dtor_typeHolder(); } diff --git a/visuald/colorizer.d b/visuald/colorizer.d index a94b0de4..3a883342 100644 --- a/visuald/colorizer.d +++ b/visuald/colorizer.d @@ -235,6 +235,7 @@ class Colorizer : DisposingComObject, IVsColorizer, ConfigModifiedListener bool mConfigRelease; bool mConfigUnittest; bool mConfigX64; + bool mConfigMSVCRT; bool mConfigCoverage; bool mConfigDoc; bool mConfigNoBoundsCheck; @@ -731,9 +732,12 @@ class Colorizer : DisposingComObject, IVsColorizer, ConfigModifiedListener case "DigitalMars": return mConfigCompiler == Compiler.DMD ? 1 : -1; case "CRuntime_DigitalMars": - return mConfigCompiler == Compiler.DMD && !mConfigX64 ? 1 : -1; + return mConfigCompiler == Compiler.DMD && !mConfigMSVCRT ? 1 : -1; case "CRuntime_Microsoft": - return mConfigCompiler == Compiler.DMD && mConfigX64 ? 1 : -1; + return (mConfigCompiler == Compiler.DMD || mConfigCompiler == Compiler.LDC) && mConfigMSVCRT ? 1 : -1; + case "MinGW": + return mConfigCompiler == Compiler.GDC || (mConfigCompiler == Compiler.LDC && !mConfigMSVCRT) ? 1 : -1; + default: assert(false, "inconsistent predefined versions"); } @@ -1404,15 +1408,17 @@ class Colorizer : DisposingComObject, IVsColorizer, ConfigModifiedListener if(mConfig) { - changes += modifyValue(mConfig.GetProjectOptions().versionids, mConfigVersions[kIndexVersion]); - changes += modifyValue(mConfig.GetProjectOptions().debugids, mConfigVersions[kIndexDebug]); - changes += modifyValue(mConfig.GetProjectOptions().release, mConfigRelease); - changes += modifyValue(mConfig.GetProjectOptions().useUnitTests, mConfigUnittest); - changes += modifyValue(mConfig.GetProjectOptions().isX86_64, mConfigX64); - changes += modifyValue(mConfig.GetProjectOptions().cov, mConfigCoverage); - changes += modifyValue(mConfig.GetProjectOptions().doDocComments, mConfigDoc); - changes += modifyValue(mConfig.GetProjectOptions().noboundscheck, mConfigNoBoundsCheck); - changes += modifyValue(mConfig.GetProjectOptions().compiler, mConfigCompiler); + ProjectOptions opts = mConfig.GetProjectOptions(); + changes += modifyValue(opts.versionids, mConfigVersions[kIndexVersion]); + changes += modifyValue(opts.debugids, mConfigVersions[kIndexDebug]); + changes += modifyValue(opts.release, mConfigRelease); + changes += modifyValue(opts.useUnitTests, mConfigUnittest); + changes += modifyValue(opts.isX86_64, mConfigX64); + changes += modifyValue(opts.useMSVCRT(), mConfigMSVCRT); + changes += modifyValue(opts.cov, mConfigCoverage); + changes += modifyValue(opts.doDocComments, mConfigDoc); + changes += modifyValue(opts.noboundscheck, mConfigNoBoundsCheck); + changes += modifyValue(opts.compiler, mConfigCompiler); } return changes != 0; } diff --git a/visuald/completion.d b/visuald/completion.d index 64f24cde..5c672067 100644 --- a/visuald/completion.d +++ b/visuald/completion.d @@ -576,7 +576,7 @@ class CompletionSet : DisposingComObject, IVsCompletionSet, IVsCompletionSetEx this(ImageList imageList, Source source) { - mImageList = LoadImageList(g_hInst, kImageCompletion.ptr, 16, 16); + mImageList = LoadImageList(g_hInst, MAKEINTRESOURCEA(BMP_COMPLETION), 16, 16); mSource = source; } diff --git a/visuald/config.d b/visuald/config.d index dc89d87b..74eb3d16 100644 --- a/visuald/config.d +++ b/visuald/config.d @@ -142,7 +142,7 @@ class ProjectOptions bool verbose; // verbose compile bool vtls; // identify thread local variables bool vgc; // List all gc allocations including hidden ones (DMD 2.066+) - ubyte symdebug; // insert debug symbolic information + ubyte symdebug; // insert debug symbolic information (0: none, 1: mago, 2: VS, 3: as debugging) bool optimize; // run optimizer ubyte cpu; // target CPU bool isX86_64; // generate X86_64 bit code @@ -291,7 +291,7 @@ class ProjectOptions void setDebug(bool dbg) { runCv2pdb = dbg; - symdebug = dbg ? 1 : 0; + symdebug = dbg ? 3 : 0; release = dbg ? 0 : 1; optimize = release; useInline = release; @@ -306,6 +306,12 @@ class ProjectOptions string objectFileExtension() { return compiler != Compiler.GDC ? "obj" : "o"; } string otherCompilerPath() { return otherDMD ? program : null; } + bool useMSVCRT() + { + return (compiler == Compiler.DMD && (isX86_64 || mscoff)) || + (compiler == Compiler.LDC); + } + @property ref CompilerDirectories compilerDirectories() { switch(compiler) @@ -317,6 +323,18 @@ class ProjectOptions } } + bool isLDCforMinGW() + { + if (compiler != Compiler.LDC) + return false; + + string installdir = Package.GetGlobalOptions().LDC.InstallDir; + if (installdir.empty) + return false; + + return std.file.exists(normalizeDir(installdir) ~ "lib/libphobos2-ldc.a"); + } + // common options with building phobos.lib string dmdCommonCompileOptions() { @@ -332,10 +350,15 @@ class ProjectOptions cmd ~= " -vtls"; if(Dversion >= 2 && vgc) cmd ~= " -vgc"; - if(symdebug == 1) + + int symdbg = symdebug; + if(symdebug == 3) + symdbg = debugEngine == 1 ? 1 : 2; + if(symdbg == 1) cmd ~= " -g"; - if(symdebug == 2) + if(symdbg == 2) cmd ~= " -gc"; + if(optimize) cmd ~= " -O"; if(useDeprecated) @@ -603,10 +626,15 @@ class ProjectOptions cmd ~= " -m32"; if(verbose) cmd ~= " -v"; - if(symdebug == 1) + + int symdbg = symdebug; + if(symdebug == 3) + symdbg = debugEngine == 1 ? 1 : 2; + if(symdbg == 1) cmd ~= " -g"; - if(symdebug == 2) + if(symdbg == 2) cmd ~= " -gc"; + if(optimize) cmd ~= " -O"; if(useDeprecated) @@ -690,12 +718,12 @@ class ProjectOptions if(compiler == Compiler.DMD) return buildDMDCommandLine(compile, performLink, deps, syntaxOnly); - if(!compile && performLink && lib == OutputType.StaticLib) - return buildARCommandLine(); - if(compiler == Compiler.LDC) return buildLDCCommandLine(compile, performLink, deps, syntaxOnly); + if(!compile && performLink && lib == OutputType.StaticLib) + return buildARCommandLine(); + return buildGDCCommandLine(compile, performLink, deps, syntaxOnly); } @@ -757,6 +785,7 @@ class ProjectOptions string linkGDCCommandLine() { string cmd; + string linkeropt = " -Wl,"; string dmdoutfile = getTargetPath(); if(usesCv2pdb()) @@ -768,7 +797,7 @@ class ProjectOptions case 0: // no map break; default: - cmd ~= " -Wl,-Map=\"$(INTDIR)\\$(SAFEPROJECTNAME).map\""; + cmd ~= linkeropt ~ "-Map=\"$(INTDIR)\\$(SAFEPROJECTNAME).map\""; break; } @@ -776,9 +805,9 @@ class ProjectOptions if(useStdLibPath) lpaths ~= tokenizeArgs(isX86_64 ? compilerDirectories.LibSearchPath64 : compilerDirectories.LibSearchPath); else - cmd ~= " -Wl,-nostdlib"; + cmd ~= linkeropt ~ "-nostdlib"; foreach(lp; lpaths) - cmd ~= " -Wl,-L," ~ quoteFilename(lp); + cmd ~= linkeropt ~ "-L," ~ quoteFilename(lp); if(lib != OutputType.StaticLib) { @@ -797,6 +826,50 @@ class ProjectOptions return cmd; } + string linkLDCCommandLine() + { + string cmd; + string linkeropt = " -L="; + + string dmdoutfile = getTargetPath(); + if(usesCv2pdb()) + dmdoutfile ~= "_cv"; + + cmd ~= " -of=" ~ quoteNormalizeFilename(dmdoutfile); + switch(mapverbosity) + { + case 0: // no map + break; + default: + cmd ~= linkeropt ~ "-Map=\"$(INTDIR)\\$(SAFEPROJECTNAME).map\""; + break; + } + + string[] lpaths = tokenizeArgs(libpaths); + if(useStdLibPath) + lpaths ~= tokenizeArgs(isX86_64 ? compilerDirectories.LibSearchPath64 : compilerDirectories.LibSearchPath); + else + cmd ~= linkeropt ~ "-nostdlib"; + foreach(lp; lpaths) + cmd ~= linkeropt ~ "-L," ~ quoteFilename(lp); + + if(lib != OutputType.StaticLib) + { + // if(createImplib) + // cmd ~= " -L/IMPLIB:$(OUTDIR)\\$(PROJECTNAME).lib"; + if(objfiles.length) + cmd ~= " " ~ objfiles; + if(deffile.length) + cmd ~= " " ~ deffile; + // added later in getCommandFileList + // if(libfiles.length) + // cmd ~= " " ~ libfiles; + if(resfile.length) + cmd ~= " " ~ resfile; + } + return cmd; + } + string optlinkCommandLine(string[] lnkfiles, string inioptions, string workdir, bool mslink) { string cmd; @@ -925,8 +998,10 @@ class ProjectOptions { if(compiler == Compiler.GDC) return linkGDCCommandLine(); + else if(isLDCforMinGW()) + return linkLDCCommandLine(); else if(compiler == Compiler.LDC) - return linkDMDCommandLine(true); + return linkDMDCommandLine(true); // MS link else return linkDMDCommandLine(isX86_64); } @@ -960,7 +1035,7 @@ class ProjectOptions { default: case Compiler.DMD: cc = (isX86_64 || mscoff ? 1 : 0); break; - case Compiler.LDC: cc = 2; break; + case Compiler.LDC: cc = (isLDCforMinGW() ? 2 : 1); break; case Compiler.GDC: cc = 3; break; } @@ -2208,13 +2283,13 @@ class Config : DisposingComObject, /////////////////////////////////////////////////////////////// // IVsProfilableProjectCfg - HRESULT SuppressSignedAssemblyWarnings(/+[retval, out]+/VARIANT_BOOL* suppress) + override HRESULT get_SuppressSignedAssemblyWarnings(/+[retval, out]+/VARIANT_BOOL* suppress) { mixin(LogCallMix); *suppress = FALSE; return S_OK; } - HRESULT LegacyWebSupportRequired(/+[retval, out]+/VARIANT_BOOL* required) + override HRESULT get_LegacyWebSupportRequired(/+[retval, out]+/VARIANT_BOOL* required) { mixin(LogCallMix); *required = FALSE; @@ -2477,7 +2552,7 @@ class Config : DisposingComObject, default: case Compiler.DMD: return mProjectOptions.mscoff || mProjectOptions.isX86_64 ? "cl" : "dmc"; case Compiler.GDC: return "gcc"; - case Compiler.LDC: return "clang"; + case Compiler.LDC: return mProjectOptions.isLDCforMinGW() ? "clang" : "cl"; } } @@ -2870,7 +2945,7 @@ class Config : DisposingComObject, else if(mProjectOptions.compiler == Compiler.LDC) cmd ~= "set LIB=" ~ lpath ~ "\n"; } - if(x64 || mscoff) + if(mProjectOptions.useMSVCRT()) { if(globOpt.WindowsSdkDir.length) cmd ~= "set WindowsSdkDir=" ~ globOpt.WindowsSdkDir ~ "\n"; @@ -2970,7 +3045,7 @@ class Config : DisposingComObject, if(!mProjectOptions.preservePaths) fname = baseName(fname); fname ~= "." ~ mProjectOptions.objectFileExtension(); - if(mProjectOptions.compiler == Compiler.DMD && !isAbsolute(fname)) + if(mProjectOptions.compiler.isIn(Compiler.DMD, Compiler.LDC) && !isAbsolute(fname)) f = mProjectOptions.objdir ~ "\\" ~ fname; else f = fname; diff --git a/visuald/dimagelist.d b/visuald/dimagelist.d index f06067e7..efc187d8 100644 --- a/visuald/dimagelist.d +++ b/visuald/dimagelist.d @@ -12,9 +12,6 @@ import stdext.string; mixin(extractDefines(import("resources.h"))); -const kImageBmp = "BMP_DIMAGELIST"; -const kImageCompletion = "BMP_COMPLETION"; - const kImageDSource = 0; const kImageProject = 1; const kImageFolderClosed = 2; diff --git a/visuald/dlangsvc.d b/visuald/dlangsvc.d index e13f7d56..0ade20e9 100644 --- a/visuald/dlangsvc.d +++ b/visuald/dlangsvc.d @@ -710,6 +710,21 @@ class LanguageService : DisposingComObject, return mSources; } + IVsTextView GetView(string filename) + { + foreach(cmgr; mCodeWinMgrs) + { + string srcfile = cmgr.mSource.GetFileName(); + if(CompareFilenames(srcfile, filename) == 0) + { + if (cmgr.mViewFilters.length) + return cmgr.mViewFilters[0].mView; + return null; + } + } + return null; + } + void setDebugger(IVsDebugger debugger) { if(mCookieDebuggerEvents && mDebugger) @@ -806,7 +821,8 @@ class LanguageService : DisposingComObject, cfgopts.cov, cfgopts.doDocComments, cfgopts.noboundscheck, cfgopts.compiler == Compiler.GDC, cfgopts.versionlevel, cfgopts.debuglevel, - cfgopts.errDeprecated, globopts.mixinAnalysis, globopts.UFCSExpansions); + cfgopts.errDeprecated, cfgopts.compiler == Compiler.LDC, + cfgopts.useMSVCRT (), globopts.mixinAnalysis, globopts.UFCSExpansions); string strimp = cfgopts.replaceEnvironment(cfgopts.fileImppath, cfg); stringImp = tokenizeArgs(strimp); diff --git a/visuald/dpackage.d b/visuald/dpackage.d index 2320d2b3..2e767cea 100644 --- a/visuald/dpackage.d +++ b/visuald/dpackage.d @@ -507,33 +507,33 @@ version(none) } // IVsInstalledProduct - override int IdBmpSplash(uint* pIdBmp) + override int get_IdBmpSplash(uint* pIdBmp) { mixin(LogCallMix); *pIdBmp = BMP_SPLASHSCRN; return S_OK; } - override int OfficialName(BSTR* pbstrName) + override int get_OfficialName(BSTR* pbstrName) { logCall("%s.ProductID(pbstrName=%s)", this, pbstrName); *pbstrName = allocwBSTR(g_packageName); return S_OK; } - override int ProductID(BSTR* pbstrPID) + override int get_ProductID(BSTR* pbstrPID) { logCall("%s.ProductID(pbstrPID=%s)", this, pbstrPID); *pbstrPID = allocBSTR(full_version); return S_OK; } - override int ProductDetails(BSTR* pbstrProductDetails) + override int get_ProductDetails(BSTR* pbstrProductDetails) { logCall("%s.ProductDetails(pbstrPID=%s)", this, pbstrProductDetails); *pbstrProductDetails = allocBSTR ("Integration of the D Programming Language into Visual Studio"); return S_OK; } - override int IdIcoLogoForAboutbox(uint* pIdIco) + override int get_IdIcoLogoForAboutbox(uint* pIdIco) { logCall("%s.IdIcoLogoForAboutbox(pIdIco=%s)", this, pIdIco); *pIdIco = ICON_ABOUTBOX; @@ -735,7 +735,7 @@ version(none) hr = E_FAIL; return hr; } - static HRESULT writeGUID(IStream pStream, ref GUID uid) + static HRESULT writeGUID(IStream pStream, ref const GUID uid) { ULONG written; HRESULT hr = pStream.Write(&uid, uid.sizeof, &written); @@ -771,21 +771,21 @@ version(none) return S_OK; } /////////////////////////// - static HRESULT readUint(IStream pStream, ref uint num) + static HRESULT readRaw(IStream pStream, void* p, uint size) { ULONG read; - HRESULT hr = pStream.Read(&num, num.sizeof, &read); - if(hr == S_OK && read != num.sizeof) + HRESULT hr = pStream.Read(p, size, &read); + if(hr == S_OK && read != size) hr = E_FAIL; return hr; } + static HRESULT readUint(IStream pStream, ref uint num) + { + return readRaw(pStream, &num, num.sizeof); + } static HRESULT readGUID(IStream pStream, ref GUID uid) { - ULONG read; - HRESULT hr = pStream.Read(&uid, uid.sizeof, &read); - if(hr == S_OK && read != uid.sizeof) - hr = E_FAIL; - return hr; + return readRaw(pStream, &uid, uid.sizeof); } static HRESULT readString(IStream pStream, ref string s) { @@ -796,13 +796,22 @@ version(none) if(len == -1) return S_FALSE; char[] buf = new char[len]; - ULONG read; - HRESULT hr = pStream.Read(buf.ptr, len, &read); - if(hr == S_OK && read != len) - hr = E_FAIL; + HRESULT hr = readRaw(pStream, buf.ptr, len); s = assumeUnique(buf); return hr; } + static HRESULT skip(IStream pStream, uint len) + { + char[256] buf; + for(; len >= buf.sizeof; len -= buf.sizeof) + if(auto hr = readRaw(pStream, buf.ptr, buf.sizeof)) + return hr; + + if(len > 0) + if(auto hr = readRaw(pStream, buf.ptr, len)) + return hr; + return S_OK; + } HRESULT WriteUserOptions(IStream pOptionsStream, in LPCOLESTR pszKey) { @@ -858,9 +867,24 @@ version(none) } } } - GUID uid; // empty GUID as end marker + GUID uid; // empty GUID as end marker of projects if(auto hr = writeGUID(pOptionsStream, uid)) return hr; + + version(writeSearchPaneState) + { + // now followed by more chunks with (iid,length) heaser + if(auto win = getSearchPane(false)) + { + if(auto hr = writeGUID(pOptionsStream, SearchPane.iid)) + return hr; + if(HRESULT hr = win.SaveViewState(pOptionsStream)) + return hr; + } + // empty GUID as end marker + if(auto hr = writeGUID(pOptionsStream, uid)) + return hr; + } } return S_OK; } @@ -873,9 +897,9 @@ version(none) return E_FAIL; scope(exit) release(srpSolution); + GUID uid; for(;;) { - GUID uid; if(auto hr = readGUID(pOptionsStream, uid)) return hr; if(uid == GUID_NULL) @@ -936,6 +960,28 @@ version(none) } } } + + version(writeSearchPaneState) + while(readGUID(pOptionsStream, uid) == S_OK) + { + if(uid == GUID_NULL) + break; + if (uid == SearchPane.iid) + { + if(auto win = getSearchPane(true)) + { + if(HRESULT hr = win.LoadViewState(pOptionsStream)) + return hr; + continue; + } + } + // skip chunk + uint len; + if(HRESULT hr = readUint(pOptionsStream, len)) + return hr; + if(HRESULT hr = skip(pOptionsStream, len)) + return hr; + } return S_OK; } @@ -1134,6 +1180,8 @@ class GlobalOptions // evaluated once at startup string WindowsSdkDir; + string UCRTSdkDir; + string UCRTVersion; string DevEnvDir; string VSInstallDir; string VCInstallDir; @@ -1219,6 +1267,7 @@ class GlobalOptions void detectWindowsSDKDir() { + // todo: detect Win10 SDK if(WindowsSdkDir.empty) { scope RegKey keySdk = new RegKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v8.1"w, false); @@ -1247,6 +1296,65 @@ class GlobalOptions WindowsSdkDir = normalizeDir(WindowsSdkDir); } + void detectUCRT() + { + if(UCRTSdkDir.empty) + { + if(char* psdk = getenv("UniversalCRTSdkDir")) + UCRTSdkDir = normalizeDir(fromMBSz(cast(immutable)psdk)); + else + { + scope RegKey keySdk = new RegKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots"w, false); + UCRTSdkDir = normalizeDir(toUTF8(keySdk.GetString("KitsRoot10"))); + } + } + if(UCRTVersion.empty) + { + if(char* pver = getenv("UCRTVersion")) + UCRTVersion = fromMBSz(cast(immutable)pver); + else if(!UCRTSdkDir.empty) + { + string rootsDir = normalizeDir(UCRTSdkDir) ~ "Lib\\"; + try + { + foreach(string f; dirEntries(rootsDir, "*", SpanMode.shallow, false)) + if(std.file.isDir(f) && f > UCRTVersion) + UCRTVersion = baseName(f); + } + catch(Exception) + { + } + } + } + } + + void detectVCInstallDir() + { + if(char* pe = getenv("VSINSTALLDIR")) + VSInstallDir = fromMBSz(cast(immutable)pe); + else + { + scope RegKey keyVS = new RegKey(hConfigKey, regConfigRoot, false); + VSInstallDir = toUTF8(keyVS.GetString("InstallDir")); + // InstallDir is ../Common7/IDE/ + VSInstallDir = normalizeDir(VSInstallDir); + VSInstallDir = dirName(dirName(VSInstallDir)); + } + VSInstallDir = normalizeDir(VSInstallDir); + } + + void detectVSInstallDir() + { + if(char* pe = getenv("VCINSTALLDIR")) + VCInstallDir = fromMBSz(cast(immutable)pe); + else + { + scope RegKey keyVS = new RegKey(hConfigKey, regConfigRoot ~ "\\Setup\\VC", false); + VCInstallDir = toUTF8(keyVS.GetString("ProductDir")); + } + VCInstallDir = normalizeDir(VCInstallDir); + } + bool initFromRegistry() { if(!getRegistryRoot()) @@ -1268,27 +1376,9 @@ class GlobalOptions scope RegKey keyUserOpts = new RegKey(hUserKey, regUserRoot ~ regPathToolsOptions, false); detectWindowsSDKDir(); - - if(char* pe = getenv("VSINSTALLDIR")) - VSInstallDir = fromMBSz(cast(immutable)pe); - else - { - scope RegKey keyVS = new RegKey(hConfigKey, regConfigRoot, false); - VSInstallDir = toUTF8(keyVS.GetString("InstallDir")); - // InstallDir is ../Common7/IDE/ - VSInstallDir = normalizeDir(VSInstallDir); - VSInstallDir = dirName(dirName(VSInstallDir)); - } - VSInstallDir = normalizeDir(VSInstallDir); - - if(char* pe = getenv("VCINSTALLDIR")) - VCInstallDir = fromMBSz(cast(immutable)pe); - else - { - scope RegKey keyVS = new RegKey(hConfigKey, regConfigRoot ~ "\\Setup\\VC", false); - VCInstallDir = toUTF8(keyVS.GetString("ProductDir")); - } - VCInstallDir = normalizeDir(VCInstallDir); + detectUCRT(); + detectVSInstallDir(); + detectVCInstallDir(); wstring getWStringOpt(wstring tag, wstring def = null) { @@ -1299,9 +1389,9 @@ class GlobalOptions { return toUTF8(getWStringOpt(tag, def)); } - string getPathsOpt(wstring tag, wstring def = null) + string getPathsOpt(wstring tag, string def = null) { - return replaceSemiCrLf(toUTF8(getWStringOpt(tag, def))); + return replaceSemiCrLf(toUTF8(getWStringOpt(tag, to!wstring(def)))); } int getIntOpt(wstring tag, int def = 0) { @@ -1334,43 +1424,60 @@ class GlobalOptions pasteIndent = getBoolOpt("pasteIndent", true); scope RegKey keyDParser = new RegKey(HKEY_CLASSES_ROOT, "CLSID\\{002a2de9-8bb6-484d-AA05-7e4ad4084715}", false); - useDParser = getBoolOpt("useDParser2", keyDParser.key !is null); + useDParser = true; // getBoolOpt("useDParser2", keyDParser.key !is null); mixinAnalysis = getBoolOpt("mixinAnalysis", false); UFCSExpansions = getBoolOpt("UFCSExpansions", true); - wstring getDefaultDMDLibPath64() + string getDefaultLibPathCOFF64() + { + string libpath = r"$(VCInstallDir)\lib\amd64"; + if(std.file.exists(VCInstallDir ~ "lib\\legacy_stdio_definitions.lib")) + libpath ~= "\n$(UCRTSdkDir)Lib\\$(UCRTVersion)\\ucrt\\x64"; + + if(WindowsSdkDir.length) + { + if(std.file.exists(WindowsSdkDir ~ r"lib\x64\kernel32.lib")) + libpath ~= "\n$(WindowsSdkDir)lib\\x64"; + else if(std.file.exists(WindowsSdkDir ~ r"Lib\win8\um\x64\kernel32.lib")) // SDK 8.0 + libpath ~= "\n$(WindowsSdkDir)Lib\\win8\\um\\x64"; + else if(std.file.exists(WindowsSdkDir ~ r"Lib\winv6.3\um\x64\kernel32.lib")) // SDK 8.1 + libpath ~= "\n$(WindowsSdkDir)Lib\\winv6.3\\um\\x64"; + } + return libpath; + } + + string getDefaultLibPathCOFF32() { - wstring libpath = r"$(VCInstallDir)\lib\amd64"; + string libpath = r"$(VCInstallDir)\lib"; + if(std.file.exists(VCInstallDir ~ "lib\\legacy_stdio_definitions.lib")) + libpath ~= "\n$(UCRTSdkDir)Lib\\$(UCRTVersion)\\ucrt\\x86"; + if(WindowsSdkDir.length) { - if(std.file.exists(WindowsSdkDir ~ r"lib\x64")) - libpath ~= to!wstring("\n$(WindowsSdkDir)lib\\x64"); - else if(std.file.exists(WindowsSdkDir ~ r"Lib\win8\um\x64")) // SDK 8.0 - libpath ~= to!wstring("\n$(WindowsSdkDir)Lib\\win8\\um\\x64"); - else if(std.file.exists(WindowsSdkDir ~ r"Lib\\winv6.3\\um\\x64")) // SDK 8.1 - libpath ~= to!wstring("\n$(WindowsSdkDir)Lib\\winv6.3\\um\\x64"); + if(std.file.exists(WindowsSdkDir ~ r"lib\kernel32.lib")) + libpath ~= "\n$(WindowsSdkDir)lib"; + else if(std.file.exists(WindowsSdkDir ~ r"Lib\win8\um\x86\kernel32.lib")) // SDK 8.0 + libpath ~= "\n$(WindowsSdkDir)Lib\\win8\\um\\x86"; + else if(std.file.exists(WindowsSdkDir ~ r"Lib\winv6.3\um\x86\kernel32.lib")) // SDK 8.1 + libpath ~= "\n$(WindowsSdkDir)Lib\\winv6.3\\um\\x86"; } return libpath; } // overwrite by user config - void readCompilerOptions(string compiler)(ref CompilerDirectories opt, wstring defLibPath64, wstring defLibPath32coff = null) + void readCompilerOptions(string compiler)(ref CompilerDirectories opt) { enum bool dmd = compiler == "DMD"; enum string prefix = dmd ? "" : compiler ~ "."; opt.InstallDir = getStringOpt(compiler ~ "InstallDir"); - wstring defDisasm32omf = `"obj2asm" -x "$(InputPath)" >"$(TargetPath)"`; - wstring defDisasm32 = `"$(VCInstallDir)\bin\dumpbin" /disasm:nobytes "$(InputPath)" >"$(TargetPath)"`; - wstring defDisasm64 = `"$(VCInstallDir)\bin\amd64\dumpbin" /disasm:nobytes "$(InputPath)" >"$(TargetPath)"`; - - opt.ExeSearchPath = getPathsOpt(prefix ~ "ExeSearchPath"); - opt.LibSearchPath = getPathsOpt(prefix ~ "LibSearchPath"); - opt.ImpSearchPath = getPathsOpt(prefix ~ "ImpSearchPath"); - opt.DisasmCommand = getPathsOpt(prefix ~ "DisasmCommand", dmd ? defDisasm32omf : defDisasm32); - opt.ExeSearchPath64 = getPathsOpt(prefix ~ "ExeSearchPath64", to!wstring(opt.ExeSearchPath)); - opt.LibSearchPath64 = getPathsOpt(prefix ~ "LibSearchPath64", defLibPath64); - opt.DisasmCommand64 = getPathsOpt(prefix ~ "DisasmCommand64", defDisasm64); + opt.ExeSearchPath = getPathsOpt(prefix ~ "ExeSearchPath", opt.ExeSearchPath); + opt.LibSearchPath = getPathsOpt(prefix ~ "LibSearchPath", opt.LibSearchPath); + opt.ImpSearchPath = getPathsOpt(prefix ~ "ImpSearchPath", opt.ImpSearchPath); + opt.DisasmCommand = getPathsOpt(prefix ~ "DisasmCommand", opt.DisasmCommand); + opt.ExeSearchPath64 = getPathsOpt(prefix ~ "ExeSearchPath64", opt.ExeSearchPath64); + opt.LibSearchPath64 = getPathsOpt(prefix ~ "LibSearchPath64", opt.LibSearchPath64); + opt.DisasmCommand64 = getPathsOpt(prefix ~ "DisasmCommand64", opt.DisasmCommand64); opt.overrideIni64 = getBoolOpt(prefix ~ "overrideIni64", dmd); opt.overrideLinker64 = getStringOpt(prefix ~ "overrideLinker64", dmd ? r"$(VCINSTALLDIR)\bin\link.exe" : ""); @@ -1378,20 +1485,46 @@ class GlobalOptions if (dmd) { - opt.ExeSearchPath32coff = getPathsOpt(prefix ~ "ExeSearchPath32coff", to!wstring(opt.ExeSearchPath)); - opt.LibSearchPath32coff = getPathsOpt(prefix ~ "LibSearchPath32coff", defLibPath32coff); - opt.DisasmCommand32coff = getPathsOpt(prefix ~ "DisasmCommand32coff", defDisasm32); + opt.ExeSearchPath32coff = getPathsOpt(prefix ~ "ExeSearchPath32coff", opt.ExeSearchPath32coff); + opt.LibSearchPath32coff = getPathsOpt(prefix ~ "LibSearchPath32coff", opt.LibSearchPath32coff); + opt.DisasmCommand32coff = getPathsOpt(prefix ~ "DisasmCommand32coff", opt.DisasmCommand32coff); opt.overrideIni32coff = getBoolOpt(prefix ~ "overrideIni32coff", dmd); opt.overrideLinker32coff = getStringOpt(prefix ~ "overrideLinker32coff", dmd ? r"$(VCINSTALLDIR)\bin\link.exe" : ""); opt.overrideOptions32coff = getStringOpt(prefix ~ "overrideOptions32coff"); } } - readCompilerOptions!"DMD"(DMD, getDefaultDMDLibPath64()); - readCompilerOptions!"GDC"(GDC, null); - readCompilerOptions!"LDC"(LDC, null); + // put dmd bin folder at the end to avoid trouble with link.exe (dmd does not need search path) + // $(WindowsSdkDir)\bin needed for rc.exe + // $(VCInstallDir)\bin needed to compile C + link.exe + DLLs + // $(VSINSTALLDIR)\Common7\IDE needed for some VS versions for cv2pdb + DMD.ExeSearchPath = r"$(VCInstallDir)\bin;$(VSINSTALLDIR)\Common7\IDE;$(WindowsSdkDir)\bin;$(DMDInstallDir)windows\bin"; + DMD.ExeSearchPath64 = DMD.ExeSearchPath; + DMD.ExeSearchPath32coff = DMD.ExeSearchPath; + GDC.ExeSearchPath = r"$(GDCInstallDir)\bin;$(VSINSTALLDIR)\Common7\IDE;$(WindowsSdkDir)\bin"; + GDC.ExeSearchPath64 = GDC.ExeSearchPath; + LDC.ExeSearchPath = r"$(LDCInstallDir)\bin;$(VCInstallDir)\bin;$(VSINSTALLDIR)\Common7\IDE;$(WindowsSdkDir)\bin"; + LDC.ExeSearchPath64 = r"$(LDCInstallDir)\bin;$(VCInstallDir)\bin\amd64;$(WindowsSdkDir)\bin"; + + DMD.LibSearchPath64 = getDefaultLibPathCOFF64(); + LDC.LibSearchPath64 = DMD.LibSearchPath64; + DMD.LibSearchPath32coff = getDefaultLibPathCOFF32(); + LDC.LibSearchPath = DMD.LibSearchPath32coff; + + DMD.DisasmCommand = `"obj2asm" -x "$(InputPath)" >"$(TargetPath)"`; + DMD.DisasmCommand64 = `"$(VCInstallDir)\bin\amd64\dumpbin" /disasm:nobytes "$(InputPath)" >"$(TargetPath)"`; + DMD.DisasmCommand32coff = `"$(VCInstallDir)\bin\dumpbin" /disasm:nobytes "$(InputPath)" >"$(TargetPath)"`; + + GDC.DisasmCommand = DMD.DisasmCommand32coff; + LDC.DisasmCommand = DMD.DisasmCommand32coff; + GDC.DisasmCommand64 = DMD.DisasmCommand64; + LDC.DisasmCommand64 = DMD.DisasmCommand64; + + readCompilerOptions!"DMD"(DMD); + readCompilerOptions!"GDC"(GDC); + readCompilerOptions!"LDC"(LDC); JSNSearchPath = getPathsOpt("JSNSearchPath"); - IncSearchPath = getStringOpt("IncSearchPath"); + IncSearchPath = getStringOpt("IncSearchPath", r"$(WindowsSdkDir)\include;$(VCInstallDir)\include"); VDServerIID = getStringOpt("VDServerIID"); compileAndRunOpts = getStringOpt("compileAndRunOpts", "-unittest"); compileAndDbgOpts = getStringOpt("compileAndDbgOpts", "-g"); @@ -1560,6 +1693,8 @@ class GlobalOptions replacements["GDCINSTALLDIR"] = normalizeDir(GDC.InstallDir); replacements["LDCINSTALLDIR"] = normalizeDir(LDC.InstallDir); replacements["WINDOWSSDKDIR"] = WindowsSdkDir; + replacements["UCRTSDKDIR"] = UCRTSdkDir; + replacements["UCRTVERSION"] = UCRTVersion; replacements["DEVENVDIR"] = DevEnvDir; replacements["VCINSTALLDIR"] = VCInstallDir; replacements["VSINSTALLDIR"] = VSInstallDir; @@ -2008,7 +2143,13 @@ class GlobalOptions { scope RegKey keyUserOpts = new RegKey(hUserKey, regUserRoot ~ r"\General", false); string theme = toUTF8(keyUserOpts.GetString("CurrentTheme")).toLower; - return theme == "1ded0138-47ce-435e-84ef-9ec1f439b749" || theme == "{1ded0138-47ce-435e-84ef-9ec1f439b749}"; + if (theme == "1ded0138-47ce-435e-84ef-9ec1f439b749" || theme == "{1ded0138-47ce-435e-84ef-9ec1f439b749}") + return true; + + // VS2015 + scope RegKey keyUserOpts15 = new RegKey(hUserKey, regUserRoot ~ r"\ApplicationPrivateSettings\Microsoft\VisualStudio", false); + string theme15 = toUTF8(keyUserOpts15.GetString("ColorTheme")).toLower; + return theme15.endsWith("1ded0138-47ce-435e-84ef-9ec1f439b749"); } bool removeColorCache() diff --git a/visuald/dproject.d b/visuald/dproject.d index 6d5d7425..053e356a 100644 --- a/visuald/dproject.d +++ b/visuald/dproject.d @@ -48,6 +48,7 @@ import visuald.build; import visuald.config; import visuald.oledatasource; import visuald.pkgutil; +import visuald.dimagelist; import visuald.dllmain : g_hInst; @@ -1200,6 +1201,18 @@ class Project : CVsHierarchy, break; } } + else if(*pguidCmdGroup == g_commandSetCLSID) + { + switch(Cmd.cmdID) + { + case CmdNewPackage: + case CmdNewFilter: + return GetProjectNode().QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText); + default: + break; + } + } + // Node commands if (!fHandled) { @@ -2667,7 +2680,7 @@ HRESULT DustMiteProject() cmdfile = npath ~ "build.dustmite.bat"; std.file.write(cmdfile, cmdline); cmdfile = makeRelative(cmdfile, npath); - string dustcmd = quoteFilename(cmdfile) ~ " | find " ~ quoteFilename(errmsg); + string dustcmd = quoteFilename(cmdfile) ~ " | find \"" ~ errmsg ~ "\""; dustcmd = dustcmd.replace("\"", "\\\""); string intdir = makeFilenameAbsolute(cfg.GetIntermediateDir(), workdir); diff --git a/visuald/expansionprovider.d b/visuald/expansionprovider.d index df51b1b0..45212eef 100644 --- a/visuald/expansionprovider.d +++ b/visuald/expansionprovider.d @@ -64,14 +64,14 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient string titleToInsert; string pathToInsert; - this(Source src) + this(Source src) { mSource = src; vsExpansion = qi_cast!(IVsExpansion)(src.GetTextLines()); assert(vsExpansion); } - override void Dispose() + override void Dispose() { EndTemplateEditing(true); mSource = null; @@ -86,14 +86,14 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient return super.QueryInterface(riid, pvObject); } - bool HandleQueryStatus(ref GUID guidCmdGroup, uint nCmdId, out int hr) + bool HandleQueryStatus(ref GUID guidCmdGroup, uint nCmdId, out int hr) { // in case there's something to conditinally support later on... hr = 0; return false; } - bool GetExpansionSpan(TextSpan *span) + bool GetExpansionSpan(TextSpan *span) { assert(expansionSession); @@ -173,7 +173,7 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient return false; } - bool DisplayExpansionBrowser(IVsTextView view, string prompt, string[] types, bool includeNullType, + bool DisplayExpansionBrowser(IVsTextView view, string prompt, string[] types, bool includeNullType, string[] kinds, bool includeNullKind) { if (expansionActive) @@ -219,7 +219,7 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient freeBSTR(type); foreach(kind; bstrKinds) freeBSTR(kind); - + return SUCCEEDED(hr); } @@ -271,7 +271,7 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient if (expansionActive) EndTemplateEditing(true); - int hr = vsExpansion.InsertNamedExpansion(title, path, pos, this, + int hr = vsExpansion.InsertNamedExpansion(title, path, pos, this, g_languageCLSID, showDisambiguationUI ? 1 : 0, &expansionSession); if (hr != S_OK || !expansionSession) @@ -294,7 +294,7 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient /// Returns S_OK if match found, S_FALSE if expansion UI is shown, and error otherwise int InvokeExpansionByShortcut(IVsTextView view, wstring shortcut, ref TextSpan span, bool showDisambiguationUI, out string title, out string path) { - if (expansionActive) + if (expansionActive) EndTemplateEditing(true); mView = view; @@ -314,14 +314,14 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient scope(exit) release(exmgr); BSTR bstrPath, bstrTitle; - int hr = exmgr.GetExpansionByShortcut(this, g_languageCLSID, _toUTF16zw(shortcut), mView, + int hr = exmgr.GetExpansionByShortcut(this, g_languageCLSID, _toUTF16zw(shortcut), mView, &span, showDisambiguationUI ? 1 : 0, &bstrPath, &bstrTitle); if(FAILED(hr) || !bstrPath || !bstrTitle) return S_FALSE; // when no shortcut found, do nothing - + if(!InsertNamedExpansion(view, bstrTitle, bstrPath, span, showDisambiguationUI)) hr = E_FAIL; - + path = detachBSTR(bstrPath); title = detachBSTR(bstrTitle); @@ -377,7 +377,7 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient case ')': if (!inParams) i = n; // terminate loop - else + else { if (inIdent) { @@ -447,9 +447,9 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient auto bstrTitle = ScopedBSTR(titleToInsert); auto bstrPath = ScopedBSTR(pathToInsert); - int hr = vsExpansion.InsertNamedExpansion(bstrTitle, bstrPath, tsInsert, + int hr = vsExpansion.InsertNamedExpansion(bstrTitle, bstrPath, tsInsert, this, g_languageCLSID, 0, &expansionSession); - + if (hr != S_OK) EndTemplateEditing(true); pathToInsert = null; @@ -477,7 +477,7 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient auto bstrField = ScopedBSTR(field); expansionSession.GetFieldSpan(bstrField, pts); - + return true; } @@ -514,7 +514,7 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient { // We should not merge edits in this case because it might clobber the // $varname$ spans which are markers for yellow boxes. - + // using (EditArray edits = new EditArray(mSource, mView, false, SR.GetString(SR.FormatSpan))) { // mSource.ReformatSpan(edits, span); // edits.ApplyEdits(); @@ -616,7 +616,7 @@ class ExpansionProvider : DisposingComObject, IVsExpansionClient //mixin(LogCallMix); BSTR text; - if(int hr = xmlFunctionNode.text(&text)) + if(int hr = xmlFunctionNode.get_text(&text)) return hr; string innerText = detachBSTR(text); *func = GetExpansionFunction(innerText, to_string(bstrFieldName)); @@ -833,4 +833,4 @@ class ExpansionFunction : DComObject, IVsExpansionFunction internal class SVsExpansionManager { } +/ -} \ No newline at end of file +} diff --git a/visuald/fileutil.d b/visuald/fileutil.d index 47b28ca7..ab92b3a5 100644 --- a/visuald/fileutil.d +++ b/visuald/fileutil.d @@ -152,6 +152,31 @@ string shortFilename(string fname) return to!string(sptr[0..len]); } +string createNewPackageInFolder(string dir, string base) +{ + string ndir = normalizeDir(dir); + dir = ndir[0..$-1]; // remove trailing '/' + if (!exists(dir) || !isDir(dir)) + return null; + + string name = base; + int num = 0; + while(exists(ndir ~ name) || exists(ndir ~ name ~ ".d") || exists(ndir ~ name ~ ".di")) + { + num++; + name = base ~ to!string(num); + } + try + { + mkdir(ndir ~ name); + } + catch(FileException) + { + return null; + } + return name; +} + string[] findDRuntimeFiles(string path, string sub, bool deep, bool cfiles = false, bool internals = false) { string[] files; diff --git a/visuald/hierarchy.d b/visuald/hierarchy.d index 910a9a39..b80fdff4 100644 --- a/visuald/hierarchy.d +++ b/visuald/hierarchy.d @@ -154,9 +154,18 @@ class CFileNode : CHierNode, if(toLower(newname) == toLower(mFilename)) return S_OK; + bool wasOpen; + int line = -1; + int col = 0; + GetDocInfo(&wasOpen, null, null, null); + if (wasOpen) + if (auto tv = Package.GetLanguageService().GetView(oldpath)) + tv.GetCaretPos(&line, &col); + if(HRESULT hr = CloseDoc(SLNSAVEOPT_PromptSave)) return hr; - try + + tryWithExceptionToBuildOutputPane(() { std.file.rename(oldpath, newpath); @@ -165,12 +174,16 @@ class CFileNode : CHierNode, SetName(baseName(mFilename)); GetCVsHierarchy().GetProjectNode().SetProjectFileDirty(true); - } - catch(Exception e) - { - writeToBuildOutputPane(e.msg); - return returnError(E_FAIL); - } + + if (wasOpen) + if(CVsHierarchy hier = GetCVsHierarchy()) + { + hier.OpenDoc(this, false, false, true); + if (auto tv = Package.GetLanguageService().GetView(newpath)) + if (line >= 0) + tv.SetCaretPos(line, col); + } + }); return S_OK; } @@ -593,7 +606,23 @@ class CFolderNode : CHierContainer } override int SetEditLabel(in BSTR pEditLabel) { - SetName(to_string(pEditLabel)); + string label = to_string(pEditLabel); + + // only rename folder for package if no files in project folder + if(searchNode(this, (CHierNode n) { return cast(CFileNode) n !is null; }) is null) + { + string dir = GuessFolderPath(); + if (std.file.exists(dir) && std.file.isDir(dir)) + { + string newdir = normalizeDir(dirName(dir)) ~ label; + scope dg = (){ + std.file.rename(dir, newdir); + }; + if (!tryWithExceptionToBuildOutputPane(dg)) + return S_FALSE; + } + } + SetName(label); GetCVsHierarchy().OnPropertyChanged(this, VSHPROPID_Name, 0); return S_OK; } @@ -603,6 +632,8 @@ class CFolderNode : CHierContainer string pkgname = _GuessPackageName(true, null); if(pkgname.endsWith(".")) pkgname = pkgname[0..$-1]; + if(pkgname.startsWith(".")) + pkgname = pkgname[1..$]; return pkgname; } @@ -665,7 +696,17 @@ class CFolderNode : CHierContainer return pkgname; } - string _GuessFolderPath() + string GuessFolderPath() + { + string dir = _GuessFolderPath(true, null); + if(dir.length) + return dir; + + CProjectNode pProject = GetCVsHierarchy().GetProjectNode(); + return dirName(pProject.GetFullPath()); + } + + string _GuessFolderPath(bool recurseUp, CFolderNode exclude) { // check files in folder for(CHierNode pNode = GetHead(); pNode; pNode = pNode.GetNext()) @@ -674,11 +715,21 @@ class CFolderNode : CHierContainer for(CHierNode pNode = GetHead(); pNode; pNode = pNode.GetNext()) if(auto folder = cast(CFolderNode) pNode) + if(folder !is exclude) + { + string s = folder._GuessFolderPath(false, null); + if(s.length) + return dirName(s); + } + + if(recurseUp) + if(auto p = cast(CFolderNode) GetParent()) { - string s = folder._GuessFolderPath(); + string s = p._GuessFolderPath(true, this); if(s.length) - return dirName(s); + return normalizeDir(s) ~ GetName(); } + return null; } @@ -701,6 +752,7 @@ class CFolderNode : CHierContainer case VSHPROPID_EditLabel: if(var.vt != VT_BSTR) return returnError(E_INVALIDARG); + return SetEditLabel(var.bstrVal); // can fail default: return super.SetProperty(propid, var); @@ -726,8 +778,6 @@ class CFolderNode : CHierContainer { case cmdidAddNewItem: case cmdidAddExistingItem: - case ECMD_ADDFILTER: - case cmdidNewFolder: fSupported = true; fEnabled = true; break; @@ -746,7 +796,7 @@ class CFolderNode : CHierContainer { case cmdidExploreFolderInWindows: fSupported = true; - string s = _GuessFolderPath(); + string s = GuessFolderPath(); fEnabled = s.length > 0 && std.file.isDir(s); break; default: @@ -754,6 +804,20 @@ class CFolderNode : CHierContainer break; } } + else if(*pguidCmdGroup == g_commandSetCLSID) + { + switch(Cmd.cmdID) + { + case CmdNewPackage: + case CmdNewFilter: + fSupported = true; + fEnabled = true; + break; + default: + hr = OLECMDERR_E_NOTSUPPORTED; + break; + } + } else { hr = OLECMDERR_E_NOTSUPPORTED; @@ -791,10 +855,6 @@ class CFolderNode : CHierContainer hr = OnCmdAddItem(this, nCmdID == cmdidAddNewItem); break; - case ECMD_ADDFILTER: - case cmdidNewFolder: - hr = OnCmdAddFolder(); - break; default: break; } @@ -811,7 +871,20 @@ class CFolderNode : CHierContainer break; } } - + else if(*pguidCmdGroup == g_commandSetCLSID) + { + switch(nCmdID) + { + case CmdNewPackage: + hr = OnCmdAddFolder(false); + break; + case CmdNewFilter: + hr = OnCmdAddFolder(true); + break; + default: + break; + } + } if (hr == OLECMDERR_E_NOTSUPPORTED) hr = super.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); @@ -834,7 +907,7 @@ class CFolderNode : CHierContainer override uint GetContextMenu() { return IDM_VS_CTXT_FOLDERNODE; } ////////////////////////////////////////////////////////////////////// - HRESULT OnCmdAddFolder() + HRESULT OnCmdAddFolder(bool filter) { HRESULT hr = S_OK; @@ -843,7 +916,15 @@ class CFolderNode : CHierContainer // Create a new folder in the Project's folder CFolderNode pFolder = newCom!CFolderNode; - string strThisFolder = "Folder"; + string strThisFolder = "Filter"; + + if(!filter) + { + string path = GuessFolderPath(); + if (path.empty) + path = dirName(pProject.GetFullPath()); + strThisFolder = createNewPackageInFolder(path, "pkg"); + } pFolder.SetName(strThisFolder); Add(pFolder); @@ -933,7 +1014,7 @@ class CFolderNode : CHierContainer HRESULT OnExploreFolderInWindows() { - string s = _GuessFolderPath(); + string s = GuessFolderPath(); if(s.length && std.file.isDir(s)) std.process.browse(s); return S_OK; @@ -1122,6 +1203,14 @@ class CProjectNode : CFolderNode return super.GetProperty(propid, var); } + override int SetEditLabel(in BSTR pEditLabel) + { + string label = to_string(pEditLabel); + SetName(label); + GetCVsHierarchy().OnPropertyChanged(this, VSHPROPID_Name, 0); + return S_OK; + } + private: CVsTrackProjectDocuments2Helper mTrackProjectDocuments2Helper; CVsHierarchy mHierarchy; @@ -1360,7 +1449,7 @@ version(none) break; case VSHPROPID_IconImgList: var.vt = VT_I4; - auto himagelst = LoadImageList(g_hInst, kImageBmp.ptr, 16, 16); + auto himagelst = LoadImageList(g_hInst, MAKEINTRESOURCEA(BMP_DIMAGELIST), 16, 16); var.lVal = cast(int) himagelst; break; case VSHPROPID_IconHandle: diff --git a/visuald/hierutil.d b/visuald/hierutil.d index c84af1b7..05ca2d5d 100644 --- a/visuald/hierutil.d +++ b/visuald/hierutil.d @@ -13,7 +13,6 @@ import std.string; import std.file; import std.path; import std.utf; -import std.stream; import std.array; import std.conv; import core.stdc.wchar_ : wcslen; @@ -347,7 +346,7 @@ int GetDTE(dte.DTE *lppaReturn) if(!_dte) return returnError(E_NOINTERFACE); scope(exit) _dte.Release(); - return _dte.DTE(lppaReturn); + return _dte.get_DTE(lppaReturn); } @@ -364,7 +363,7 @@ string getStringProperty(dte.Properties props, string propName, string def = nul scope(exit) release(prop); VARIANT var; - hr = prop.Value(&var); + hr = prop.get_Value(&var); if(var.vt != VT_BSTR) return def; if(FAILED(hr)) @@ -385,7 +384,7 @@ int getIntProperty(dte.Properties props, string propName, int def = -1) scope(exit) release(prop); VARIANT var; - hr = prop.Value(&var); + hr = prop.get_Value(&var); if(FAILED(hr)) return def; if(var.vt == VT_I2 || var.vt == VT_UI2) @@ -405,7 +404,7 @@ string getEnvironmentFont(out int fontSize, out int charSet) dte.Properties props; BSTR bprop = allocBSTR("FontsAndColors"); BSTR bpage = allocBSTR("Dialogs and Tool Windows"); - HRESULT hr = _dte.Properties(bprop, bpage, &props); + HRESULT hr = _dte.get_Properties(bprop, bpage, &props); detachBSTR(bprop); detachBSTR(bpage); if(FAILED(hr) || !props) diff --git a/visuald/pkgutil.d b/visuald/pkgutil.d index 0d955fbf..81e232b0 100644 --- a/visuald/pkgutil.d +++ b/visuald/pkgutil.d @@ -158,6 +158,45 @@ bool tryWithExceptionToBuildOutputPane(T)(T dg, string errInfo = "") return false; } +string browseFile(HWND parentHwnd, string title, string filter, string initdir = null) +{ + if (auto pIVsUIShell = ComPtr!(IVsUIShell)(queryService!(IVsUIShell), false)) + { + wchar[260] fileName; + fileName[0] = 0; + VSOPENFILENAMEW ofn; + ofn.lStructSize = ofn.sizeof; + ofn.hwndOwner = parentHwnd; + ofn.pwzDlgTitle = toUTF16z(title); + ofn.pwzFileName = fileName.ptr; + ofn.nMaxFileName = fileName.length; + ofn.pwzInitialDir = toUTF16z(initdir); + ofn.pwzFilter = toUTF16z(filter); + if (pIVsUIShell.GetOpenFileNameViaDlg(&ofn) == S_OK) + return to!string(fileName); + } + return null; +} + +string browseDirectory(HWND parentHwnd, string title, string initdir = null) +{ + if (auto pIVsUIShell = ComPtr!(IVsUIShell)(queryService!(IVsUIShell), false)) + { + wchar[260] dirName; + dirName[0] = 0; + VSBROWSEINFOW bi; + bi.lStructSize = bi.sizeof; + bi.hwndOwner = parentHwnd; + bi.pwzDlgTitle = toUTF16z(title); + bi.pwzDirName = dirName.ptr; + bi.nMaxDirName = dirName.length; + bi.pwzInitialDir = toUTF16z(initdir); + if (pIVsUIShell.GetDirectoryViaBrowseDlg(&bi) == S_OK) + return to!string(dirName); + } + return null; +} + /////////////////////////////////////////////////////////////////////// // version = DEBUG_GC; version(DEBUG_GC) diff --git a/visuald/profiler.d b/visuald/profiler.d index 456bde63..309b1509 100644 --- a/visuald/profiler.d +++ b/visuald/profiler.d @@ -439,7 +439,7 @@ private: _wndFuncList.SendMessage(LVM_DELETEALLITEMS); _wndFuncList.SendMessage(LVM_REMOVEALLGROUPS); - HIMAGELIST himl = LoadImageList(getInstance(), kImageBmp.ptr, 16, 16); + HIMAGELIST himl = LoadImageList(getInstance(), MAKEINTRESOURCEA(BMP_DIMAGELIST), 16, 16); if(himl) _wndFuncList.SendMessage(LVM_SETIMAGELIST, LVSIL_SMALL, cast(LPARAM)himl); diff --git a/visuald/propertypage.d b/visuald/propertypage.d index 00845c52..979d7fd7 100644 --- a/visuald/propertypage.d +++ b/visuald/propertypage.d @@ -23,13 +23,17 @@ import visuald.config; import visuald.winctrl; import visuald.hierarchy; import visuald.hierutil; +import visuald.pkgutil; import visuald.chiernode; import stdext.array; +import stdext.path; +import std.array; import std.string; import std.conv; +import std.algorithm; -/*debug*/ version = DParser; +// version = DParserOption; class PropertyWindow : Window { @@ -39,16 +43,13 @@ class PropertyWindow : Window super(parent, style, title); } - override int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) + override int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) { import sdk.win32.commctrl; switch (uMsg) { case WM_SIZE: - RECT r; - GetWindowRect(&r); - int w = LOWORD(lParam); - mPropertyPage.updateSizes(r.left, w); + mPropertyPage.updateSizes(); break; case TCN_SELCHANGING: @@ -70,12 +71,12 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage { /*const*/ int kPageWidth = 370; /*const*/ int kPageHeight = 210; - /*const*/ int kMargin = 4; + /*const*/ int kMargin = 2; /*const*/ int kLabelWidth = 120; /*const*/ int kTextHeight = 20; /*const*/ int kLineHeight = 23; /*const*/ int kLineSpacing = 2; - /*const*/ int kNeededLines = 10; + /*const*/ int kNeededLines = 11; override HRESULT QueryInterface(in IID* riid, void** pvObject) { @@ -90,18 +91,18 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage override void Dispose() { + mResizableWidgets = mResizableWidgets.init; + mSite = release(mSite); foreach(obj; mObjects) release(obj); mObjects.length = 0; - mResizableWidgets = mResizableWidgets.init; - mDlgFont = deleteDialogFont(mDlgFont); } - override int SetPageSite( + override int SetPageSite( /* [in] */ IPropertyPageSite pPageSite) { mixin(LogCallMix); @@ -110,37 +111,20 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage return S_OK; } - override int Activate( + override int Activate( /* [in] */ in HWND hWndParent, /* [in] */ in RECT *pRect, /* [in] */ in BOOL bModal) { mixin(LogCallMix); - + if(mWindow) return returnError(E_FAIL); - return _Activate(new Window(hWndParent), pRect, bModal); + return _Activate(new Window(hWndParent), pRect, bModal != 0); } - - int _Activate( - /* [in] */ Window win, - /* [in] */ in RECT *pRect, - /* [in] */ in BOOL bModal) - { - if(pRect) - logCall("_Activate(" ~ to!string(*pRect) ~ ")"); - RECT pr; - win.GetWindowRect(&pr); - logCall(" parent.rect = " ~ to!string(pr) ~ ""); - - if(HWND phwnd = GetParent(win.hwnd)) - { - GetWindowRect(phwnd, &pr); - logCall(" parent.parent.rect = " ~ to!string(pr) ~ ""); - } - if(pRect) - kPageWidth = pRect.right - pRect.left; + int _Activate(Window win, const(RECT) *pRect, bool bModal) + { updateEnvironmentFont(); if(!mDlgFont) mDlgFont = newDialogFont(); @@ -149,63 +133,107 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage mCanvas = new Window(mWindow); DWORD color = GetSysColor(COLOR_BTNFACE); mCanvas.setBackground(color); + + // create with desired size to get proper alignment, then resize to parent later mCanvas.setRect(kMargin, kMargin, kPageWidth - 2 * kMargin, kPageHeight - 2 * kMargin); - mResizableWidgets ~= mCanvas; // avoid closing canvas (but not dialog) if pressing esc in MultiLineEdit controls //mCanvas.cancelCloseDelegate ~= delegate bool(Widget c) { return true; }; - - class DelegateWrapper - { - void OnCommand(Widget w, int cmd) - { - UpdateDirty(true); - } - } - DelegateWrapper delegateWrapper = new DelegateWrapper; - mCanvas.commandDelegate = &delegateWrapper.OnCommand; + mCanvas.commandDelegate = &OnCommand; CreateControls(); UpdateControls(); + updateSizes(); mEnableUpdateDirty = true; return S_OK; } + extern(D) void OnCommand(Widget w, int cmd) + { + UpdateDirty(true); + } + override int Deactivate() { mixin(LogCallMix); if(mWindow) { - mWindow.Dispose(); - mWindow = null; + auto win = mWindow; mCanvas = null; + mWindow = null; + win.Dispose(); } return S_OK; //return returnError(E_NOTIMPL); } - void updateSizes(int windowLeft, int width) + void updateSizes() + { + if (!mWindow || !mCanvas) + return; + + RECT r, pr; + mCanvas.GetWindowRect(&r); + mWindow.GetWindowRect(&pr); + int pageWidth = pr.right - pr.left - 2 * kMargin; + int pageHeight = pr.bottom - pr.top - 2 * kMargin; + + if (r.right - r.left == pageWidth && r.bottom - r.top == pageHeight) + return; + + mCanvas.setRect(kMargin, kMargin, pageWidth, pageHeight); + updateResizableWidgets(mCanvas); + } + + void updateResizableWidgets(Widget w) + { + if (auto patt = w in mResizableWidgets) + patt.resizeWidget(w); + + foreach(c; w.children) + updateResizableWidgets(c); + + } + + void addResizableWidget(Widget w, Attachment att) + { + AttachData attData = AttachData(att); + attData.initFromWidget(w); + mResizableWidgets[w] = attData; + } + + void addTextPath(Text ctrl, string path, string sep) + { + string imp = ctrl.getText(); + if(!imp.empty() && !imp.endsWith(sep)) + imp ~= sep; + imp ~= quoteFilename(path); + ctrl.setText(imp); + } + + void addBrowsePath(Text ctrl, bool dir, string reldir, string sep, string title, string filter = null) { - foreach(w; mResizableWidgets) + string path; + if(dir) + path = browseDirectory(mCanvas.hwnd, title, reldir); + else + path = browseFile(mCanvas.hwnd, title, filter, reldir); + if (!path.empty) { - RECT r; - if(w && w.hwnd) - { - w.GetWindowRect(&r); - r.right = windowLeft + width - kMargin; - w.SetWindowPos(null, &r, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); - } + if(reldir) + path = makeRelative(path, reldir); + + addTextPath(ctrl, path, sep); } } void calcMetric() { updateEnvironmentFont(); - kMargin = 4; if(!mDlgFont) mDlgFont = newDialogFont(); @@ -229,7 +257,7 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage kPageHeight = kLineHeight * kNeededLines + 2 * kMargin; } - override int GetPageInfo( + override int GetPageInfo( /* [out] */ PROPPAGEINFO *pPageInfo) { mixin(LogCallMix); @@ -248,7 +276,7 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage return S_OK; } - override int SetObjects( + override int SetObjects( /* [in] */ in ULONG cObjects, /* [size_is][in] */ IUnknown *ppUnk) { @@ -270,7 +298,7 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage return S_OK; } - override int Show( + override int Show( /* [in] */ in UINT nCmdShow) { logCall("%s.Show(nCmdShow=%s)", this, _toLog(nCmdShow)); @@ -280,21 +308,22 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage //return returnError(E_NOTIMPL); } - override int Move( + override int Move( /* [in] */ in RECT *pRect) { mixin(LogCallMix); - return returnError(E_NOTIMPL); + updateSizes(); + return S_OK; //returnError(E_NOTIMPL); } - override int Help( + override int Help( /* [in] */ in wchar* pszHelpDir) { logCall("%s.Help(pszHelpDir=%s)", this, _toLog(pszHelpDir)); return returnError(E_NOTIMPL); } - override int TranslateAccelerator( + override int TranslateAccelerator( /* [in] */ in MSG *pMsg) { mixin(LogCallMix2); @@ -304,7 +333,7 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage } // IVsPropertyPage - override int CategoryTitle( + override int get_CategoryTitle( /* [in] */ in UINT iLevel, /* [retval][out] */ BSTR *pbstrCategory) { @@ -326,7 +355,7 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage } // IVsPropertyPage2 - override int GetProperty( + override int GetProperty( /* [in] */ in VSPPPID propid, /* [out] */ VARIANT *pvar) { @@ -343,7 +372,7 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage return returnError(DISP_E_MEMBERNOTFOUND); } - override int SetProperty( + override int SetProperty( /* [in] */ in VSPPPID propid, /* [in] */ in VARIANT var) { @@ -358,7 +387,30 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage mSite.OnStatusChange(PROPPAGESTATUS_DIRTY | PROPPAGESTATUS_VALIDATE); } + static int getWidgetWidth(Widget w, int def) + { + RECT pr; + if(w && w.GetWindowRect(&pr)) + return pr.right - pr.left; + return def; + } + void AddControl(string label, Widget w) + { + AddControl(label, w, null, 0); + } + + void AddControl(string label, Widget w, Button btn) + { + AddControl(label, w, btn, 0); + } + + void AddControl(string label, Widget w, short attachY) + { + AddControl(label, w, null, attachY); + } + + void AddControl(string label, Widget w, Button btn, short resizeY) { int x = kLabelWidth; auto cb = cast(CheckBox) w; @@ -371,18 +423,31 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage if(mt || tc) lines = mLinesPerMultiLine; + int pageWidth = getWidgetWidth(w ? w.parent : null, kPageWidth); + if (btn) + pageWidth -= kLineHeight; int labelWidth = 0; + int margin = tc ? 0 : kMargin; if(label.length) { Label lab = new Label(w ? w.parent : null, label); int off = ((kLineHeight - kLineSpacing) - 16) / 2; - labelWidth = w ? kLabelWidth : kPageWidth - 2*kMargin; - lab.setRect(0, mLineY + off, labelWidth, kLineHeight - kLineSpacing); - } + labelWidth = w ? kLabelWidth : pageWidth - 2*margin; + lab.setRect(0, mLineY + off, labelWidth, kLineHeight - kLineSpacing); + + if(mAttachY > 0) + { + Attachment att = kAttachNone; + att.vdiv = 1000; + att.top = att.bottom = mAttachY; + addResizableWidget(lab, att); + } + } else if (cb || tc) { x -= mUnindentCheckBox; } + int h = lines * kLineHeight - kLineSpacing; if(cast(Text) w && lines == 1) { @@ -390,23 +455,43 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage } else if(cb) h -= 2; + else if(tc) + h += tc.getFrameHeight() - kLineHeight; //else if(cast(ComboBox) w) // h -= 4; - int y = mLineY + (lines * kLineHeight - kLineSpacing - h) / 2; + int yspacing = (lines * kLineHeight - kLineSpacing - h) / 2; + int y = mLineY + max(0, yspacing); if(w) - w.setRect(x, y, kPageWidth - 2*kMargin - labelWidth, h); - mLineY += lines * kLineHeight; - if(w) - mResizableWidgets ~= w; + { + w.setRect(x, y, pageWidth - 2*margin - labelWidth, h); + Attachment att = kAttachLeftRight; + att.vdiv = 1000; + att.top = mAttachY; + att.bottom = cast(short)(mAttachY + resizeY); + addResizableWidget(w, att); + } + if(btn) + { + btn.setRect(pageWidth - kMargin, y, kLineHeight, kLineHeight - kLineSpacing); + Attachment att = kAttachRight; + att.vdiv = 1000; + att.top = att.bottom = mAttachY; + addResizableWidget(btn, att); + } + mLineY += max(h, lines * kLineHeight); + mAttachY += resizeY; } void AddHorizontalLine() { auto w = new Label(mCanvas); w.AddWindowStyle(SS_ETCHEDFRAME, SS_TYPEMASK); - w.setRect(0, mLineY + 2, kPageWidth - 2*kMargin, 2); - mResizableWidgets ~= w; + w.setRect(0, mLineY + 2, getWidgetWidth(mCanvas, kPageWidth) - 2*kMargin, 2); + Attachment att = kAttachLeftRight; + att.vdiv = 1000; + att.top = att.bottom = mAttachY; + addResizableWidget(w, att); mLineY += 6; } @@ -430,7 +515,7 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage abstract string GetCategoryName(); abstract string GetPageName(); - Widget[] mResizableWidgets; + AttachData[Widget] mResizableWidgets; HFONT mDlgFont; IUnknown[] mObjects; IPropertyPageSite mSite; @@ -438,12 +523,13 @@ abstract class PropertyPage : DisposingComObject, IPropertyPage, IVsPropertyPage Window mCanvas; bool mEnableUpdateDirty; int mLineY; + short mAttachY = 0; // fraction of 1000 int mLinesPerMultiLine = 4; int mUnindentCheckBox = 120; //16; } /////////////////////////////////////////////////////////////////////////////// -class ProjectPropertyPage : PropertyPage, ConfigModifiedListener +class ProjectPropertyPage : PropertyPage, ConfigModifiedListener { abstract void SetControls(ProjectOptions options); abstract int DoApply(ProjectOptions options, ProjectOptions refoptions); @@ -478,9 +564,9 @@ class ProjectPropertyPage : PropertyPage, ConfigModifiedListener { if(auto cfg = GetConfig()) cfg.RemoveModifiedListener(this); - + int rc = super.SetObjects(cObjects, ppUnk); - + if(auto cfg = GetConfig()) cfg.AddModifiedListener(this); @@ -503,6 +589,13 @@ class ProjectPropertyPage : PropertyPage, ConfigModifiedListener return null; } + string GetProjectDir() + { + if(auto cfg = GetConfig()) + return cfg.GetProjectDir(); + return null; + } + /*override*/ int IsPageDirty() { mixin(LogCallMix); @@ -656,18 +749,18 @@ class CommonPropertyPage : ProjectPropertyPage override string GetCategoryName() { return ""; } override string GetPageName() { return "General"; } - override void CreateControls() + override void CreateControls() { AddControl("Build System", mCbBuildSystem = new ComboBox(mCanvas, [ "Visual D", "dsss", "rebuild" ], false)); mCbBuildSystem.setSelection(0); mCbBuildSystem.setEnabled(false); } - override void SetControls(ProjectOptions options) + override void SetControls(ProjectOptions options) { } - override int DoApply(ProjectOptions options, ProjectOptions refoptions) + override int DoApply(ProjectOptions options, ProjectOptions refoptions) { - return 0; + return 0; } ComboBox mCbBuildSystem; @@ -679,25 +772,25 @@ class GeneralPropertyPage : ProjectPropertyPage override string GetPageName() { return "General"; } __gshared const float[] selectableVersions = [ 1, 2 ]; - + override void CreateControls() { string[] versions; foreach(ver; selectableVersions) versions ~= "D" ~ to!(string)(ver); //versions[$-1] ~= "+"; - + AddControl("Compiler", mCompiler = new ComboBox(mCanvas, [ "DMD", "GDC", "LDC" ], false)); AddControl("D-Version", mDVersion = new ComboBox(mCanvas, versions, false)); - AddControl("Output Type", mCbOutputType = new ComboBox(mCanvas, + AddControl("Output Type", mCbOutputType = new ComboBox(mCanvas, [ "Executable", "Library", "DLL" ], false)); - AddControl("Subsystem", mCbSubsystem = new ComboBox(mCanvas, + AddControl("Subsystem", mCbSubsystem = new ComboBox(mCanvas, [ "Not set", "Console", "Windows", "Native", "Posix" ], false)); AddControl("Output Path", mOutputPath = new Text(mCanvas)); AddControl("Intermediate Path", mIntermediatePath = new Text(mCanvas)); AddControl("Files to clean", mFilesToClean = new Text(mCanvas)); - AddControl("Compilation", mSingleFileComp = new ComboBox(mCanvas, - [ "Combined compile and link", "Single file compilation", + AddControl("Compilation", mSingleFileComp = new ComboBox(mCanvas, + [ "Combined compile and link", "Single file compilation", "Separate compile and link", "Compile only (use Post-build command to link)" ], false)); } @@ -707,7 +800,7 @@ class GeneralPropertyPage : ProjectPropertyPage while(ver < selectableVersions.length - 1 && selectableVersions[ver+1] <= options.Dversion) ver++; mDVersion.setSelection(ver); - + mCompiler.setSelection(options.compiler); mSingleFileComp.setSelection(options.compilationModel); mCbOutputType.setSelection(options.lib); @@ -747,12 +840,35 @@ class DebuggingPropertyPage : ProjectPropertyPage override string GetCategoryName() { return ""; } override string GetPageName() { return "Debugging"; } + enum ID_DBGCOMMAND = 1020; + enum ID_DBGDIR = 1021; + + extern(D) override void OnCommand(Widget w, int cmd) + { + switch(cmd) + { + case ID_DBGCOMMAND: + if(auto file = browseFile(mCanvas.hwnd, "Select executable", "Executables\0*.exe\0All Files\0*.*\0")) + mCommand.setText(file); + break; + case ID_DBGDIR: + if(auto dir = browseDirectory(mCanvas.hwnd, "Select working directory")) + mWorkingDir.setText(dir); + break; + default: + break; + } + super.OnCommand(w, cmd); + } + override void CreateControls() { Label lbl; - AddControl("Command", mCommand = new Text(mCanvas)); + auto btn = new Button(mCanvas, "...", ID_DBGCOMMAND); + AddControl("Command", mCommand = new Text(mCanvas), btn); AddControl("Command Arguments", mArguments = new Text(mCanvas)); - AddControl("Working Directory", mWorkingDir = new Text(mCanvas)); + btn = new Button(mCanvas, "...", ID_DBGDIR); + AddControl("Working Directory", mWorkingDir = new Text(mCanvas), btn); AddControl("", mAttach = new CheckBox(mCanvas, "Attach to running process")); AddControl("Remote Machine", mRemote = new Text(mCanvas)); AddControl("Debugger", mDebugEngine = new ComboBox(mCanvas, [ "Visual Studio", "Mago", "Visual Studio (x86 Mixed Mode)" ], false)); @@ -821,11 +937,38 @@ class DmdGeneralPropertyPage : ProjectPropertyPage override string GetCategoryName() { return "Compiler"; } override string GetPageName() { return "General"; } + enum ID_IMPORTPATH = 1030; + enum ID_STRINGIMPORTPATH = 1031; + + void addImportDir(Text ctrl, string title) + { + addBrowsePath(ctrl, true, GetProjectDir(), ";", title); + } + + extern(D) override void OnCommand(Widget w, int cmd) + { + switch(cmd) + { + case ID_IMPORTPATH: + addImportDir(mAddImports, "Add import path"); + break; + case ID_STRINGIMPORTPATH: + addImportDir(mStringImports, "Add string import path"); + break; + default: + break; + } + super.OnCommand(w, cmd); + } + + override void CreateControls() { //AddControl("", mUseStandard = new CheckBox(mCanvas, "Use Standard Import Paths")); - AddControl("Additional Imports", mAddImports = new Text(mCanvas)); - AddControl("String Imports", mStringImports = new Text(mCanvas)); + auto btn = new Button(mCanvas, "+", ID_IMPORTPATH); + AddControl("Additional Import Paths", mAddImports = new Text(mCanvas), btn); + btn = new Button(mCanvas, "+", ID_STRINGIMPORTPATH); + AddControl("String Import Paths", mStringImports = new Text(mCanvas), btn); AddControl("Version Identifiers", mVersionIdentifiers = new Text(mCanvas)); AddControl("Debug Identifiers", mDebugIdentifiers = new Text(mCanvas)); AddHorizontalLine(); @@ -898,13 +1041,31 @@ class DmdDebugPropertyPage : ProjectPropertyPage override string GetCategoryName() { return "Compiler"; } override string GetPageName() { return "Debug"; } + enum ID_BROWSECV2PDB = 1010; + + extern(D) override void OnCommand(Widget w, int cmd) + { + switch(cmd) + { + case ID_BROWSECV2PDB: + if(auto file = browseFile(mCanvas.hwnd, "Select cv2pdb executable", "Executables\0*.exe\0All Files\0*.*\0")) + mPathCv2pdb.setText(file); + break; + default: + break; + } + super.OnCommand(w, cmd); + } + override void CreateControls() { + string[] dbgInfoOpt = [ "None", "Symbolic (suitable for Mago)", "Symbolic (suitable for VS debug engine)", "Symbolic (suitable for selected debug engine)" ]; AddControl("Debug Mode", mDebugMode = new ComboBox(mCanvas, [ "Off (release)", "On" ], false)); - AddControl("Debug Info", mDebugInfo = new ComboBox(mCanvas, [ "None", "Symbolic (suitable for Mago)", "Symbolic (suitable for VS debug engine)" ], false)); + AddControl("Debug Info", mDebugInfo = new ComboBox(mCanvas, dbgInfoOpt, false)); AddHorizontalLine(); AddControl("", mRunCv2pdb = new CheckBox(mCanvas, "Run cv2pdb to Convert Debug Info")); - AddControl("Path to cv2pdb", mPathCv2pdb = new Text(mCanvas)); + auto btn = new Button(mCanvas, "...", ID_BROWSECV2PDB); + AddControl("Path to cv2pdb", mPathCv2pdb = new Text(mCanvas), btn); AddControl("", mCv2pdbPre2043 = new CheckBox(mCanvas, "Assume old associative array implementation (before dmd 2.043)")); AddControl("", mCv2pdbNoDemangle = new CheckBox(mCanvas, "Do not demangle symbols")); AddControl("", mCv2pdbEnumType = new CheckBox(mCanvas, "Use enumerator types")); @@ -916,7 +1077,7 @@ class DmdDebugPropertyPage : ProjectPropertyPage super.UpdateDirty(bDirty); EnableControls(); } - + void EnableControls() { mRunCv2pdb.setEnabled(mCanRunCv2PDB); @@ -998,10 +1159,10 @@ class DmdCodeGenPropertyPage : ProjectPropertyPage override void SetControls(ProjectOptions options) { - mProfiling.setChecked(options.trace); - mCodeCov.setChecked(options.cov); + mProfiling.setChecked(options.trace); + mCodeCov.setChecked(options.cov); mOptimizer.setChecked(options.optimize); - mNoboundscheck.setChecked(options.noboundscheck); + mNoboundscheck.setChecked(options.noboundscheck); mUnitTests.setChecked(options.useUnitTests); mInline.setChecked(options.useInline); mNoFloat.setChecked(options.nofloat); @@ -1114,7 +1275,7 @@ class DmdDocPropertyPage : ProjectPropertyPage AddControl("Documentation file", mDocFile = new Text(mCanvas)); AddControl("Documentation dir", mDocDir = new Text(mCanvas)); AddControl("CanDyDOC module", mModulesDDoc = new Text(mCanvas)); - + AddControl("", mGenHdr = new CheckBox(mCanvas, "Generate interface headers")); AddControl("Header file", mHdrFile = new Text(mCanvas)); AddControl("Header directory", mHdrDir = new Text(mCanvas)); @@ -1128,13 +1289,13 @@ class DmdDocPropertyPage : ProjectPropertyPage super.UpdateDirty(bDirty); EnableControls(); } - + void EnableControls() { mDocDir.setEnabled(mGenDoc.isChecked()); mDocFile.setEnabled(mGenDoc.isChecked()); mModulesDDoc.setEnabled(mGenDoc.isChecked()); - + mHdrDir.setEnabled(mGenHdr.isChecked()); mHdrFile.setEnabled(mGenHdr.isChecked()); @@ -1152,7 +1313,7 @@ class DmdDocPropertyPage : ProjectPropertyPage mHdrFile.setText(options.hdrname); mGenJSON.setChecked(options.doXGeneration); mJSONFile.setText(options.xfilename); - + EnableControls(); } @@ -1197,17 +1358,17 @@ class DmdOutputPropertyPage : ProjectPropertyPage override void SetControls(ProjectOptions options) { - mMultiObj.setChecked(options.multiobj); - mPreservePaths.setChecked(options.preservePaths); - mMsCoff32.setChecked(options.mscoff); + mMultiObj.setChecked(options.multiobj); + mPreservePaths.setChecked(options.preservePaths); + mMsCoff32.setChecked(options.mscoff); } override int DoApply(ProjectOptions options, ProjectOptions refoptions) { int changes = 0; - changes += changeOption(mMultiObj.isChecked(), options.multiobj, refoptions.multiobj); - changes += changeOption(mPreservePaths.isChecked(), options.preservePaths, refoptions.preservePaths); - changes += changeOption(mMsCoff32.isChecked(), options.mscoff, refoptions.mscoff); + changes += changeOption(mMultiObj.isChecked(), options.multiobj, refoptions.multiobj); + changes += changeOption(mPreservePaths.isChecked(), options.preservePaths, refoptions.preservePaths); + changes += changeOption(mMsCoff32.isChecked(), options.mscoff, refoptions.mscoff); return changes; } @@ -1232,16 +1393,55 @@ class DmdLinkerPropertyPage : ProjectPropertyPage EnableControls(); } + enum ID_OBJECTFILES = 1050; + enum ID_LIBRARYFILES = 1051; + enum ID_LIBRARYPATHS = 1052; + enum ID_DEFFILE = 1053; + enum ID_RESFILE = 1054; + + extern(D) override void OnCommand(Widget w, int cmd) + { + switch(cmd) + { + case ID_OBJECTFILES: + addBrowsePath(mObjFiles, false, GetProjectDir(), " ", "Add object file", "Object files\0*.obj\0All Files\0*.*\0"); + break; + case ID_LIBRARYFILES: + addBrowsePath(mLibFiles, false, GetProjectDir(), " ", "Add library file", "Library files\0*.lib\0All Files\0*.*\0"); + break; + case ID_LIBRARYPATHS: + addBrowsePath(mLibPaths, true, GetProjectDir(), " ", "Add library path"); + break; + + case ID_DEFFILE: + if(auto file = browseFile(mCanvas.hwnd, "Select definition file", "Definition files\0*.def\0All Files\0*.*\0", GetProjectDir())) + mDefFile.setText(makeRelative(file, GetProjectDir())); + break; + case ID_RESFILE: + if(auto file = browseFile(mCanvas.hwnd, "Select resource file", "Resource files\0*.res\0All Files\0*.*\0", GetProjectDir())) + mResFile.setText(makeRelative(file, GetProjectDir())); + break; + default: + break; + } + super.OnCommand(w, cmd); + } + override void CreateControls() { AddControl("Output File", mExeFile = new Text(mCanvas)); - AddControl("Object Files", mObjFiles = new Text(mCanvas)); - AddControl("Library Files", mLibFiles = new Text(mCanvas)); - AddControl("Library Search Path", mLibPaths = new Text(mCanvas)); + auto btn = new Button(mCanvas, "+", ID_OBJECTFILES); + AddControl("Object Files", mObjFiles = new Text(mCanvas), btn); + btn = new Button(mCanvas, "+", ID_LIBRARYFILES); + AddControl("Library Files", mLibFiles = new Text(mCanvas), btn); + btn = new Button(mCanvas, "+", ID_LIBRARYPATHS); + AddControl("Library Search Path", mLibPaths = new Text(mCanvas), btn); //AddControl("Library search paths only work if you have modified sc.ini to include DMD_LIB!", null); - AddControl("Definition File", mDefFile = new Text(mCanvas)); - AddControl("Resource File", mResFile = new Text(mCanvas)); - AddControl("Generate Map File", mGenMap = new ComboBox(mCanvas, + btn = new Button(mCanvas, "...", ID_DEFFILE); + AddControl("Definition File", mDefFile = new Text(mCanvas), btn); + btn = new Button(mCanvas, "...", ID_RESFILE); + AddControl("Resource File", mResFile = new Text(mCanvas), btn); + AddControl("Generate Map File", mGenMap = new ComboBox(mCanvas, [ "Minimum", "Symbols By Address", "Standard", "Full", "With cross references" ], false)); AddControl("", mImplib = new CheckBox(mCanvas, "Create import library")); AddControl("", mPrivatePhobos = new CheckBox(mCanvas, "Build and use local version of phobos with same compiler options")); @@ -1254,20 +1454,20 @@ class DmdLinkerPropertyPage : ProjectPropertyPage if(ProjectOptions options = GetProjectOptions()) mCRuntime.setEnabled(options.isX86_64 || options.mscoff); } - + override void SetControls(ProjectOptions options) { - mExeFile.setText(options.exefile); - mObjFiles.setText(options.objfiles); + mExeFile.setText(options.exefile); + mObjFiles.setText(options.objfiles); mLibFiles.setText(options.libfiles); mLibPaths.setText(options.libpaths); - mDefFile.setText(options.deffile); - mResFile.setText(options.resfile); - mGenMap.setSelection(options.mapverbosity); + mDefFile.setText(options.deffile); + mResFile.setText(options.resfile); + mGenMap.setSelection(options.mapverbosity); mImplib.setChecked(options.createImplib); mUseStdLibPath.setChecked(options.useStdLibPath); mPrivatePhobos.setChecked(options.privatePhobos); - mCRuntime.setSelection(options.cRuntime); + mCRuntime.setSelection(options.cRuntime); EnableControls(); } @@ -1275,17 +1475,17 @@ class DmdLinkerPropertyPage : ProjectPropertyPage override int DoApply(ProjectOptions options, ProjectOptions refoptions) { int changes = 0; - changes += changeOption(mExeFile.getText(), options.exefile, refoptions.exefile); - changes += changeOption(mObjFiles.getText(), options.objfiles, refoptions.objfiles); - changes += changeOption(mLibFiles.getText(), options.libfiles, refoptions.libfiles); - changes += changeOption(mLibPaths.getText(), options.libpaths, refoptions.libpaths); - changes += changeOption(mDefFile.getText(), options.deffile, refoptions.deffile); - changes += changeOption(mResFile.getText(), options.resfile, refoptions.resfile); - changes += changeOption(cast(uint) mGenMap.getSelection(), options.mapverbosity, refoptions.mapverbosity); - changes += changeOption(mImplib.isChecked(), options.createImplib, refoptions.createImplib); + changes += changeOption(mExeFile.getText(), options.exefile, refoptions.exefile); + changes += changeOption(mObjFiles.getText(), options.objfiles, refoptions.objfiles); + changes += changeOption(mLibFiles.getText(), options.libfiles, refoptions.libfiles); + changes += changeOption(mLibPaths.getText(), options.libpaths, refoptions.libpaths); + changes += changeOption(mDefFile.getText(), options.deffile, refoptions.deffile); + changes += changeOption(mResFile.getText(), options.resfile, refoptions.resfile); + changes += changeOption(cast(uint) mGenMap.getSelection(), options.mapverbosity, refoptions.mapverbosity); + changes += changeOption(mImplib.isChecked(), options.createImplib, refoptions.createImplib); changes += changeOption(mUseStdLibPath.isChecked(), options.useStdLibPath, refoptions.useStdLibPath); changes += changeOption(mPrivatePhobos.isChecked(), options.privatePhobos, refoptions.privatePhobos); - changes += changeOption(cast(uint) mCRuntime.getSelection(), options.cRuntime, refoptions.cRuntime); + changes += changeOption(cast(uint) mCRuntime.getSelection(), options.cRuntime, refoptions.cRuntime); return changes; } @@ -1309,24 +1509,26 @@ class DmdEventsPropertyPage : ProjectPropertyPage override void CreateControls() { - AddControl("Pre-Build Command", mPreCmd = new MultiLineText(mCanvas)); - AddControl("Post-Build Command", mPostCmd = new MultiLineText(mCanvas)); + mLinesPerMultiLine = 5; + AddControl("Pre-Build Command", mPreCmd = new MultiLineText(mCanvas), 500); + AddControl("Post-Build Command", mPostCmd = new MultiLineText(mCanvas), 500); Label lab = new Label(mCanvas, "Use \"if errorlevel 1 goto reportError\" to cancel on error"); - lab.setRect(0, kPageHeight - kLineHeight, kPageWidth, kLineHeight); + lab.setRect(0, mLineY, getWidgetWidth(mCanvas, kPageWidth), kLineHeight); + addResizableWidget(lab, kAttachBottom); } override void SetControls(ProjectOptions options) { - mPreCmd.setText(options.preBuildCommand); - mPostCmd.setText(options.postBuildCommand); + mPreCmd.setText(options.preBuildCommand); + mPostCmd.setText(options.postBuildCommand); } override int DoApply(ProjectOptions options, ProjectOptions refoptions) { int changes = 0; - changes += changeOption(mPreCmd.getText(), options.preBuildCommand, refoptions.preBuildCommand); - changes += changeOption(mPostCmd.getText(), options.postBuildCommand, refoptions.postBuildCommand); + changes += changeOption(mPreCmd.getText(), options.preBuildCommand, refoptions.preBuildCommand); + changes += changeOption(mPostCmd.getText(), options.postBuildCommand, refoptions.postBuildCommand); return changes; } @@ -1341,8 +1543,9 @@ class DmdCmdLinePropertyPage : ProjectPropertyPage override void CreateControls() { - AddControl("Command line", mCmdLine = new MultiLineText(mCanvas, "", 0, true)); - AddControl("Additional options", mAddOpt = new MultiLineText(mCanvas)); + mLinesPerMultiLine = 5; + AddControl("Command line", mCmdLine = new MultiLineText(mCanvas, "", 0, true), 500); + AddControl("Additional options", mAddOpt = new MultiLineText(mCanvas), 500); } override void OnConfigModified() @@ -1355,13 +1558,13 @@ class DmdCmdLinePropertyPage : ProjectPropertyPage override void SetControls(ProjectOptions options) { mCmdLine.setText(options.buildCommandLine(true, true, true)); - mAddOpt.setText(options.additionalOptions); + mAddOpt.setText(options.additionalOptions); } override int DoApply(ProjectOptions options, ProjectOptions refoptions) { int changes = 0; - changes += changeOption(mAddOpt.getText(), options.additionalOptions, refoptions.additionalOptions); + changes += changeOption(mAddOpt.getText(), options.additionalOptions, refoptions.additionalOptions); return changes; } @@ -1459,7 +1662,7 @@ class FilePropertyPage : ConfigNodePropertyPage AddControl("", mPerConfig = new CheckBox(mCanvas, "per Configuration Options (apply and reopen dialog to update)")); AddControl("Build Tool", mTool = new ComboBox(mCanvas, [ "Auto", "DMD", kToolCpp, kToolResourceCompiler, "Custom", "None" ], false)); AddControl("Additional Options", mAddOpt = new Text(mCanvas)); - AddControl("Build Command", mCustomCmd = new MultiLineText(mCanvas)); + AddControl("Build Command", mCustomCmd = new MultiLineText(mCanvas), 1000); AddControl("Other Dependencies", mDependencies = new Text(mCanvas)); AddControl("Output File", mOutFile = new Text(mCanvas)); AddControl("", mLinkOut = new CheckBox(mCanvas, "Add output to link")); @@ -1504,12 +1707,12 @@ class FilePropertyPage : ConfigNodePropertyPage mInitPerConfig = node.GetPerConfigOptions(); mPerConfig.setChecked(mInitPerConfig); - mCustomCmd.setText(node.GetCustomCmd(cfgname)); - mAddOpt.setText(node.GetAdditionalOptions(cfgname)); - mDependencies.setText(node.GetDependencies(cfgname)); - mOutFile.setText(node.GetOutFile(cfgname)); - mLinkOut.setChecked(node.GetLinkOutput(cfgname)); - mUptodateWithSameTime.setChecked(node.GetUptodateWithSameTime(cfgname)); + mCustomCmd.setText(node.GetCustomCmd(cfgname)); + mAddOpt.setText(node.GetAdditionalOptions(cfgname)); + mDependencies.setText(node.GetDependencies(cfgname)); + mOutFile.setText(node.GetOutFile(cfgname)); + mLinkOut.setChecked(node.GetLinkOutput(cfgname)); + mUptodateWithSameTime.setChecked(node.GetUptodateWithSameTime(cfgname)); enableControls(tool); } @@ -1521,15 +1724,15 @@ class FilePropertyPage : ConfigNodePropertyPage string tool = mTool.getText(); if(tool == "Auto") tool = ""; - changes += changeOptionDg!bool(mPerConfig.isChecked(), &node.SetPerConfigOptions, refnode.GetPerConfigOptions()); - changes += changeOptionDg!string(tool, (s) => node.SetTool(cfgname, s), refnode.GetTool(cfgname)); - changes += changeOptionDg!string(mCustomCmd.getText(), (s) => node.SetCustomCmd(cfgname, s), refnode.GetCustomCmd(cfgname)); - changes += changeOptionDg!string(mAddOpt.getText(), (s) => node.SetAdditionalOptions(cfgname, s), refnode.GetAdditionalOptions(cfgname)); - changes += changeOptionDg!string(mDependencies.getText(), (s) => node.SetDependencies(cfgname, s), refnode.GetDependencies(cfgname)); - changes += changeOptionDg!string(mOutFile.getText(), (s) => node.SetOutFile(cfgname, s), refnode.GetOutFile(cfgname)); - changes += changeOptionDg!bool(mLinkOut.isChecked(), (b) => node.SetLinkOutput(cfgname, b), refnode.GetLinkOutput(cfgname)); - changes += changeOptionDg!bool(mUptodateWithSameTime.isChecked(), - (b) => node.SetUptodateWithSameTime(cfgname, b), refnode.GetUptodateWithSameTime(cfgname)); + changes += changeOptionDg!bool(mPerConfig.isChecked(), &node.SetPerConfigOptions, refnode.GetPerConfigOptions()); + changes += changeOptionDg!string(tool, (s) => node.SetTool(cfgname, s), refnode.GetTool(cfgname)); + changes += changeOptionDg!string(mCustomCmd.getText(), (s) => node.SetCustomCmd(cfgname, s), refnode.GetCustomCmd(cfgname)); + changes += changeOptionDg!string(mAddOpt.getText(), (s) => node.SetAdditionalOptions(cfgname, s), refnode.GetAdditionalOptions(cfgname)); + changes += changeOptionDg!string(mDependencies.getText(), (s) => node.SetDependencies(cfgname, s), refnode.GetDependencies(cfgname)); + changes += changeOptionDg!string(mOutFile.getText(), (s) => node.SetOutFile(cfgname, s), refnode.GetOutFile(cfgname)); + changes += changeOptionDg!bool(mLinkOut.isChecked(), (b) => node.SetLinkOutput(cfgname, b), refnode.GetLinkOutput(cfgname)); + changes += changeOptionDg!bool(mUptodateWithSameTime.isChecked(), + (b) => node.SetUptodateWithSameTime(cfgname, b), refnode.GetUptodateWithSameTime(cfgname)); enableControls(tool); return changes; } @@ -1549,68 +1752,140 @@ class FilePropertyPage : ConfigNodePropertyPage /////////////////////////////////////////////////////////////////////////////// class DirPropertyPage : GlobalPropertyPage { + enum ID_BROWSEINSTALLDIR = 1000; + enum ID_IMPORTDIR = 1001; + enum ID_EXEPATH32 = 1002; + enum ID_EXEPATH64 = 1003; + enum ID_EXEPATH32COFF = 1004; + enum ID_LIBPATH32 = 1005; + enum ID_LIBPATH64 = 1006; + enum ID_LIBPATH32COFF = 1007; + enum ID_LINKER64 = 1008; + enum ID_LINKER32COFF = 1009; + this(GlobalOptions options) { super(options); kNeededLines = 13; } + void addBrowseDir(MultiLineText ctrl, string title) + { + addBrowsePath(ctrl, true, null, "\n", title); + } + + extern(D) override void OnCommand(Widget w, int cmd) + { + switch(cmd) + { + case ID_BROWSEINSTALLDIR: + if(auto dir = browseDirectory(mCanvas.hwnd, "Select installation directory")) + mDmdPath.setText(dir); + break; + case ID_IMPORTDIR: + addBrowseDir(mImpPath, "Add import directory"); + break; + + case ID_EXEPATH32: + addBrowseDir(mExePath, "Add executable directory"); + break; + case ID_EXEPATH64: + addBrowseDir(mExePath64, "Add executable directory"); + break; + case ID_EXEPATH32COFF: + addBrowseDir(mExePath32coff, "Add executable directory"); + break; + + case ID_LIBPATH32: + addBrowseDir(mLibPath, "Add library directory"); + break; + case ID_LIBPATH64: + addBrowseDir(mLibPath64, "Add library directory"); + break; + case ID_LIBPATH32COFF: + addBrowseDir(mLibPath32coff, "Add library directory"); + break; + + case ID_LINKER64: + if(auto file = browseFile(mCanvas.hwnd, "Select linker executable", "Executables\0*.exe\0All Files\0*.*\0")) + mLinkerExecutable64.setText(file); + break; + case ID_LINKER32COFF: + if(auto file = browseFile(mCanvas.hwnd, "Select linker executable", "Executables\0*.exe\0All Files\0*.*\0")) + mLinkerExecutable32coff.setText(file); + break; + default: + break; + } + super.OnCommand(w, cmd); + } + void dirCreateControls(string name, string overrideIni) { - AddControl(name ~ " install path", mDmdPath = new Text(mCanvas)); + auto btn = new Button(mCanvas, "...", ID_BROWSEINSTALLDIR); + AddControl(name ~ " install path", mDmdPath = new Text(mCanvas), btn); mLinesPerMultiLine = 2; - AddControl("Import paths", mImpPath = new MultiLineText(mCanvas)); + btn = new Button(mCanvas, "+", ID_IMPORTDIR); + AddControl("Import paths", mImpPath = new MultiLineText(mCanvas), btn, 300); + mLinesPerMultiLine = 10; string[] archs = ["Win32", "x64"]; if(overrideIni.length) archs ~= "Win32-COFF"; - AddControl("", mTabArch = new TabControl(mCanvas, archs)); + AddControl("", mTabArch = new TabControl(mCanvas, archs), 700); auto page32 = mTabArch.pages[0]; if(auto w = cast(Window)page32) w.commandDelegate = mCanvas.commandDelegate; - mResizableWidgets ~= page32; - kPageWidth -= 6; mLineY = 0; + mAttachY = 0; mLinesPerMultiLine = 3; - AddControl("Executable paths", mExePath = new MultiLineText(page32)); + btn = new Button(page32, "+", ID_EXEPATH32); + AddControl("Executable paths", mExePath = new MultiLineText(page32), btn, 500); mLinesPerMultiLine = 2; - AddControl("Library paths", mLibPath = new MultiLineText(page32)); + btn = new Button(page32, "+", ID_LIBPATH32); + AddControl("Library paths", mLibPath = new MultiLineText(page32), btn, 500); AddControl("Disassemble Command", mDisasmCommand = new Text(page32)); auto page64 = mTabArch.pages[1]; if(auto w = cast(Window)page64) w.commandDelegate = mCanvas.commandDelegate; - mResizableWidgets ~= page64; mLineY = 0; + mAttachY = 0; mLinesPerMultiLine = 3; - AddControl("Executable paths", mExePath64 = new MultiLineText(page64)); + btn = new Button(page64, "+", ID_EXEPATH64); + AddControl("Executable paths", mExePath64 = new MultiLineText(page64), btn, 500); mLinesPerMultiLine = 2; - AddControl("Library paths", mLibPath64 = new MultiLineText(page64)); + btn = new Button(page64, "+", ID_LIBPATH64); + AddControl("Library paths", mLibPath64 = new MultiLineText(page64), btn, 500); AddControl("Disassemble Command", mDisasmCommand64 = new Text(page64)); if(overrideIni.length) { AddControl("", mOverrideIni64 = new CheckBox(page64, overrideIni)); - AddControl("Linker", mLinkerExecutable64 = new Text(page64)); + btn = new Button(page64, "...", ID_LINKER64); + AddControl("Linker", mLinkerExecutable64 = new Text(page64), btn); AddControl("Additional options", mLinkerOptions64 = new Text(page64)); auto page32coff = mTabArch.pages[2]; if(auto w = cast(Window)page32coff) w.commandDelegate = mCanvas.commandDelegate; - mResizableWidgets ~= page32coff; mLineY = 0; + mAttachY = 0; mLinesPerMultiLine = 3; - AddControl("Executable paths", mExePath32coff = new MultiLineText(page32coff)); + btn = new Button(page32coff, "+", ID_EXEPATH32COFF); + AddControl("Executable paths", mExePath32coff = new MultiLineText(page32coff), btn, 500); mLinesPerMultiLine = 2; - AddControl("Library paths", mLibPath32coff = new MultiLineText(page32coff)); + btn = new Button(page32coff, "+", ID_LIBPATH32COFF); + AddControl("Library paths", mLibPath32coff = new MultiLineText(page32coff), btn, 500); AddControl("Disassemble Command", mDisasmCommand32coff = new Text(page32coff)); AddControl("", mOverrideIni32coff = new CheckBox(page32coff, overrideIni)); - AddControl("Linker", mLinkerExecutable32coff = new Text(page32coff)); + btn = new Button(page32coff, "...", ID_LINKER32COFF); + AddControl("Linker", mLinkerExecutable32coff = new Text(page32coff), btn); AddControl("Additional options", mLinkerOptions32coff = new Text(page32coff)); } } @@ -1676,26 +1951,26 @@ class DirPropertyPage : GlobalPropertyPage int changes = 0; changes += changeOption(mDmdPath.getText(), opt.InstallDir, refopt.InstallDir); - changes += changeOption(mExePath.getText(), opt.ExeSearchPath, refopt.ExeSearchPath); - changes += changeOption(mImpPath.getText(), opt.ImpSearchPath, refopt.ImpSearchPath); - changes += changeOption(mLibPath.getText(), opt.LibSearchPath, refopt.LibSearchPath); + changes += changeOption(mExePath.getText(), opt.ExeSearchPath, refopt.ExeSearchPath); + changes += changeOption(mImpPath.getText(), opt.ImpSearchPath, refopt.ImpSearchPath); + changes += changeOption(mLibPath.getText(), opt.LibSearchPath, refopt.LibSearchPath); changes += changeOption(mDisasmCommand.getText(), opt.DisasmCommand, refopt.DisasmCommand); - changes += changeOption(mExePath64.getText(), opt.ExeSearchPath64, refopt.ExeSearchPath64); + changes += changeOption(mExePath64.getText(), opt.ExeSearchPath64, refopt.ExeSearchPath64); changes += changeOption(mLibPath64.getText(), opt.LibSearchPath64, refopt.LibSearchPath64); changes += changeOption(mDisasmCommand64.getText(), opt.DisasmCommand64, refopt.DisasmCommand64); if(mOverrideIni64) { - changes += changeOption(mOverrideIni64.isChecked(), opt.overrideIni64, refopt.overrideIni64); + changes += changeOption(mOverrideIni64.isChecked(), opt.overrideIni64, refopt.overrideIni64); changes += changeOption(mLinkerExecutable64.getText(), opt.overrideLinker64, refopt.overrideLinker64); - changes += changeOption(mLinkerOptions64.getText(), opt.overrideOptions64, refopt.overrideOptions64); + changes += changeOption(mLinkerOptions64.getText(), opt.overrideOptions64, refopt.overrideOptions64); } if(mOverrideIni32coff) { - changes += changeOption(mExePath32coff.getText(), opt.ExeSearchPath32coff, refopt.ExeSearchPath32coff); + changes += changeOption(mExePath32coff.getText(), opt.ExeSearchPath32coff, refopt.ExeSearchPath32coff); changes += changeOption(mLibPath32coff.getText(), opt.LibSearchPath32coff, refopt.LibSearchPath32coff); - changes += changeOption(mOverrideIni32coff.isChecked(), opt.overrideIni32coff, refopt.overrideIni32coff); - changes += changeOption(mLinkerExecutable32coff.getText(), opt.overrideLinker32coff, refopt.overrideLinker32coff); - changes += changeOption(mLinkerOptions32coff.getText(), opt.overrideOptions32coff, refopt.overrideOptions32coff); + changes += changeOption(mOverrideIni32coff.isChecked(), opt.overrideIni32coff, refopt.overrideIni32coff); + changes += changeOption(mLinkerExecutable32coff.getText(), opt.overrideLinker32coff, refopt.overrideLinker32coff); + changes += changeOption(mLinkerOptions32coff.getText(), opt.overrideOptions32coff, refopt.overrideOptions32coff); changes += changeOption(mDisasmCommand32coff.getText(), opt.DisasmCommand32coff, refopt.DisasmCommand32coff); } return changes; @@ -1811,7 +2086,7 @@ class ToolsProperty2Page : GlobalPropertyPage AddControl("", mDemangleError = new CheckBox(mCanvas, "Demangle names in link errors/disassembly")); AddControl("", mOptlinkDeps = new CheckBox(mCanvas, "Monitor linker dependencies")); AddHorizontalLine(); - //AddControl("Remove project item", mDeleteFiles = + //AddControl("Remove project item", mDeleteFiles = // new ComboBox(mCanvas, [ "Do not delete file on disk", "Ask", "Delete file on disk" ])); mLinesPerMultiLine = 2; AddControl("JSON paths", mJSNPath = new MultiLineText(mCanvas)); @@ -1841,18 +2116,18 @@ class ToolsProperty2Page : GlobalPropertyPage override int DoApply(GlobalOptions opts, GlobalOptions refopts) { int changes = 0; - changes += changeOption(mTimeBuilds.isChecked(), opts.timeBuilds, refopts.timeBuilds); - changes += changeOption(mSortProjects.isChecked(), opts.sortProjects, refopts.sortProjects); - changes += changeOption(mShowUptodate.isChecked(), opts.showUptodateFailure, refopts.showUptodateFailure); - changes += changeOption(mStopSlnBuild.isChecked(), opts.stopSolutionBuild, refopts.stopSolutionBuild); - changes += changeOption(mDemangleError.isChecked(), opts.demangleError, refopts.demangleError); - changes += changeOption(mOptlinkDeps.isChecked(), opts.optlinkDeps, refopts.optlinkDeps); - //changes += changeOption(cast(byte) (mDeleteFiles.getSelection() - 1), opts.deleteFiles, refopts.deleteFiles); - changes += changeOption(mIncPath.getText(), opts.IncSearchPath, refopts.IncSearchPath); - changes += changeOption(mJSNPath.getText(), opts.JSNSearchPath, refopts.JSNSearchPath); - changes += changeOption(mCompileAndRunOpts.getText(), opts.compileAndRunOpts, refopts.compileAndRunOpts); - changes += changeOption(mCompileAndDbgOpts.getText(), opts.compileAndDbgOpts, refopts.compileAndDbgOpts); - changes += changeOption(mCompileAndDbgEngine.getSelection(), opts.compileAndDbgEngine, refopts.compileAndDbgEngine); + changes += changeOption(mTimeBuilds.isChecked(), opts.timeBuilds, refopts.timeBuilds); + changes += changeOption(mSortProjects.isChecked(), opts.sortProjects, refopts.sortProjects); + changes += changeOption(mShowUptodate.isChecked(), opts.showUptodateFailure, refopts.showUptodateFailure); + changes += changeOption(mStopSlnBuild.isChecked(), opts.stopSolutionBuild, refopts.stopSolutionBuild); + changes += changeOption(mDemangleError.isChecked(), opts.demangleError, refopts.demangleError); + changes += changeOption(mOptlinkDeps.isChecked(), opts.optlinkDeps, refopts.optlinkDeps); + //changes += changeOption(cast(byte) (mDeleteFiles.getSelection() - 1), opts.deleteFiles, refopts.deleteFiles); + changes += changeOption(mIncPath.getText(), opts.IncSearchPath, refopts.IncSearchPath); + changes += changeOption(mJSNPath.getText(), opts.JSNSearchPath, refopts.JSNSearchPath); + changes += changeOption(mCompileAndRunOpts.getText(), opts.compileAndRunOpts, refopts.compileAndRunOpts); + changes += changeOption(mCompileAndDbgOpts.getText(), opts.compileAndDbgOpts, refopts.compileAndDbgOpts); + changes += changeOption(mCompileAndDbgEngine.getSelection(), opts.compileAndDbgEngine, refopts.compileAndDbgEngine); return changes; } @@ -1885,7 +2160,7 @@ class ColorizerPropertyPage : GlobalPropertyPage override void CreateControls() { AddControl("", mColorizeVersions = new CheckBox(mCanvas, "Colorize version and debug statements")); - AddControl("Colored types", mUserTypes = new MultiLineText(mCanvas)); + AddControl("Colored types", mUserTypes = new MultiLineText(mCanvas), 1000); AddHorizontalLine(); AddControl("", mColorizeCoverage = new CheckBox(mCanvas, "Colorize coverage from .LST file")); AddControl("", mShowCoverageMargin = new CheckBox(mCanvas, "Show coverage margin")); @@ -1911,13 +2186,13 @@ class ColorizerPropertyPage : GlobalPropertyPage override int DoApply(GlobalOptions opts, GlobalOptions refopts) { int changes = 0; - changes += changeOption(mColorizeVersions.isChecked(), opts.ColorizeVersions, refopts.ColorizeVersions); - changes += changeOption(mColorizeCoverage.isChecked(), opts.ColorizeCoverage, refopts.ColorizeCoverage); - changes += changeOption(mShowCoverageMargin.isChecked(), opts.showCoverageMargin, refopts.showCoverageMargin); - changes += changeOption(mAutoOutlining.isChecked(), opts.autoOutlining, refopts.autoOutlining); - changes += changeOption(mParseSource.isChecked(), opts.parseSource, refopts.parseSource); - changes += changeOption(mPasteIndent.isChecked(), opts.pasteIndent, refopts.pasteIndent); - changes += changeOption(mUserTypes.getText(), opts.UserTypesSpec, refopts.UserTypesSpec); + changes += changeOption(mColorizeVersions.isChecked(), opts.ColorizeVersions, refopts.ColorizeVersions); + changes += changeOption(mColorizeCoverage.isChecked(), opts.ColorizeCoverage, refopts.ColorizeCoverage); + changes += changeOption(mShowCoverageMargin.isChecked(), opts.showCoverageMargin, refopts.showCoverageMargin); + changes += changeOption(mAutoOutlining.isChecked(), opts.autoOutlining, refopts.autoOutlining); + changes += changeOption(mParseSource.isChecked(), opts.parseSource, refopts.parseSource); + changes += changeOption(mPasteIndent.isChecked(), opts.pasteIndent, refopts.pasteIndent); + changes += changeOption(mUserTypes.getText(), opts.UserTypesSpec, refopts.UserTypesSpec); return changes; } @@ -1949,7 +2224,7 @@ class IntellisensePropertyPage : GlobalPropertyPage AddControl("Show expansion when", mExpandTrigger = new ComboBox(mCanvas, [ "pressing Ctrl+Space", "writing '.'", "writing an identifier" ], false)); AddControl("", mShowTypeInTooltip = new CheckBox(mCanvas, "Show type of expressions in tool tip")); AddControl("", mSemanticGotoDef = new CheckBox(mCanvas, "Use semantic analysis for \"Goto Definition\" (before trying JSON info)")); - version(DParser) AddControl("", mUseDParser = new CheckBox(mCanvas, "Use Alexander Bothe's D parsing engine for semantic analysis")); + version(DParserOption) AddControl("", mUseDParser = new CheckBox(mCanvas, "Use Alexander Bothe's D parsing engine for semantic analysis")); AddControl("", mMixinAnalysis = new CheckBox(mCanvas, "Enable mixin analysis")); AddControl("", mUFCSExpansions = new CheckBox(mCanvas, "Enable UFCS expansions")); } @@ -1962,8 +2237,8 @@ class IntellisensePropertyPage : GlobalPropertyPage void EnableControls() { - version(DParser) bool useDParser = mUseDParser.isChecked(); - else bool useDParser = false; + version(DParserOption) bool useDParser = mUseDParser.isChecked(); + else bool useDParser = true; mMixinAnalysis.setEnabled(useDParser); mUFCSExpansions.setEnabled(useDParser); } @@ -1976,7 +2251,7 @@ class IntellisensePropertyPage : GlobalPropertyPage mExpandTrigger.setSelection(opts.expandTrigger); mShowTypeInTooltip.setChecked(opts.showTypeInTooltip); mSemanticGotoDef.setChecked(opts.semanticGotoDef); - version(DParser) mUseDParser.setChecked(opts.useDParser); + version(DParserOption) mUseDParser.setChecked(opts.useDParser); mMixinAnalysis.setChecked(opts.mixinAnalysis); mUFCSExpansions.setChecked(opts.UFCSExpansions); @@ -1986,15 +2261,15 @@ class IntellisensePropertyPage : GlobalPropertyPage override int DoApply(GlobalOptions opts, GlobalOptions refopts) { int changes = 0; - changes += changeOption(mExpandSemantics.isChecked(), opts.expandFromSemantics, refopts.expandFromSemantics); - changes += changeOption(mExpandFromBuffer.isChecked(), opts.expandFromBuffer, refopts.expandFromBuffer); - changes += changeOption(mExpandFromJSON.isChecked(), opts.expandFromJSON, refopts.expandFromJSON); - changes += changeOption(cast(byte) mExpandTrigger.getSelection(), opts.expandTrigger, refopts.expandTrigger); - changes += changeOption(mShowTypeInTooltip.isChecked(), opts.showTypeInTooltip, refopts.showTypeInTooltip); - changes += changeOption(mSemanticGotoDef.isChecked(), opts.semanticGotoDef, refopts.semanticGotoDef); - version(DParser) changes += changeOption(mUseDParser.isChecked(), opts.useDParser, refopts.useDParser); - changes += changeOption(mMixinAnalysis.isChecked(), opts.mixinAnalysis, refopts.mixinAnalysis); - changes += changeOption(mUFCSExpansions.isChecked(), opts.UFCSExpansions, refopts.UFCSExpansions); + changes += changeOption(mExpandSemantics.isChecked(), opts.expandFromSemantics, refopts.expandFromSemantics); + changes += changeOption(mExpandFromBuffer.isChecked(), opts.expandFromBuffer, refopts.expandFromBuffer); + changes += changeOption(mExpandFromJSON.isChecked(), opts.expandFromJSON, refopts.expandFromJSON); + changes += changeOption(cast(byte) mExpandTrigger.getSelection(), opts.expandTrigger, refopts.expandTrigger); + changes += changeOption(mShowTypeInTooltip.isChecked(), opts.showTypeInTooltip, refopts.showTypeInTooltip); + changes += changeOption(mSemanticGotoDef.isChecked(), opts.semanticGotoDef, refopts.semanticGotoDef); + version(DParserOption) changes += changeOption(mUseDParser.isChecked(), opts.useDParser, refopts.useDParser); + changes += changeOption(mMixinAnalysis.isChecked(), opts.mixinAnalysis, refopts.mixinAnalysis); + changes += changeOption(mUFCSExpansions.isChecked(), opts.UFCSExpansions, refopts.UFCSExpansions); return changes; } @@ -2004,7 +2279,7 @@ class IntellisensePropertyPage : GlobalPropertyPage ComboBox mExpandTrigger; CheckBox mShowTypeInTooltip; CheckBox mSemanticGotoDef; - version(DParser) CheckBox mUseDParser; + version(DParserOption) CheckBox mUseDParser; CheckBox mUFCSExpansions; CheckBox mMixinAnalysis; } @@ -2035,8 +2310,8 @@ const GUID g_ToolsProperty2Page = uuid("002a2de9-8bb6-484d-9822-7e4ad40 const GUID g_ColorizerPropertyPage = uuid("002a2de9-8bb6-484d-9821-7e4ad4084715"); const GUID g_IntellisensePropertyPage = uuid("002a2de9-8bb6-484d-9823-7e4ad4084715"); -const GUID*[] guids_propertyPages = -[ +const GUID*[] guids_propertyPages = +[ &g_GeneralPropertyPage, &g_DmdGeneralPropertyPage, &g_DmdDebugPropertyPage, diff --git a/visuald/register.d b/visuald/register.d index a4fd6424..a636da37 100644 --- a/visuald/register.d +++ b/visuald/register.d @@ -117,9 +117,9 @@ class RegistryException : Exception class RegKey { - this(HKEY root, wstring keyname, bool write = true, bool chkDump = true) + this(HKEY root, wstring keyname, bool write = true, bool chkDump = true, bool x64hive = false) { - Create(root, keyname, write, chkDump); + Create(root, keyname, write, chkDump, x64hive); } ~this() @@ -143,7 +143,7 @@ class RegKey return "\""w ~ escapeString(name) ~ "\""w; } - void Create(HKEY root, wstring keyname, bool write = true, bool chkDump = true) + void Create(HKEY root, wstring keyname, bool write = true, bool chkDump = true, bool x64hive = false) { HRESULT hr; if(write && chkDump && registryRoot.length && keyname.startsWith(registryRoot)) @@ -155,12 +155,13 @@ class RegKey } else if(write) { - hr = hrRegCreateKeyEx(root, keyname, 0, null, REG_OPTION_NON_VOLATILE, KEY_WRITE, null, &key, null); + auto opt = REG_OPTION_NON_VOLATILE | (x64hive ? KEY_WOW64_64KEY : 0); + hr = hrRegCreateKeyEx(root, keyname, 0, null, opt, KEY_WRITE, null, &key, null); if(FAILED(hr)) throw new RegistryException(hr); } else - hr = hrRegOpenKeyEx(root, keyname, 0, KEY_READ, &key); + hr = hrRegOpenKeyEx(root, keyname, (x64hive ? KEY_WOW64_64KEY : 0), KEY_READ, &key); } void Set(wstring name, wstring value, bool escape = true) @@ -581,7 +582,7 @@ version(none){ // menu scope RegKey keyToolMenu = new RegKey(keyRoot, registrationRoot ~ "\\Menus"w); - keyToolMenu.Set(packageGuid, ",2001,19"); // CTMENU,version + keyToolMenu.Set(packageGuid, ",2001,20"); // CTMENU,version // Visual D settings scope RegKey keyToolOpts = new RegKey(keyRoot, registrationRoot ~ regPathToolsOptions); @@ -589,11 +590,6 @@ version(none){ keyToolOpts.Set("Package"w, packageGuid); keyToolOpts.Set("Page"w, GUID2wstring(g_ToolsProperty2Page)); - if(keyToolOpts.GetString("ExeSearchPath"w).length == 0) - keyToolOpts.Set("ExeSearchPath"w, "$(DMDInstallDir)windows\\bin;$(VSINSTALLDIR)\\Common7\\IDE;$(WindowsSdkDir)\\bin"w, false); - if(keyToolOpts.GetString("IncSearchPath"w).length == 0) - keyToolOpts.Set("IncSearchPath"w, "$(WindowsSdkDir)\\include;$(DevEnvDir)..\\..\\VC\\include"w, false); - // remove old page RegDeleteRecursive(keyRoot, registrationRoot ~ regPathToolsDirsOld); diff --git a/visuald/searchsymbol.d b/visuald/searchsymbol.d index 552528ba..2e866ffe 100644 --- a/visuald/searchsymbol.d +++ b/visuald/searchsymbol.d @@ -45,26 +45,33 @@ import core.stdc.stdio : sprintf; private IVsWindowFrame sWindowFrame; private SearchPane sSearchPane; +SearchPane getSearchPane(bool create) +{ + if(!sSearchPane && create) + sSearchPane = newCom!SearchPane; + return sSearchPane; +} + bool showSearchWindow() { + if(!getSearchPane(true)) + return false; + if(!sWindowFrame) { auto pIVsUIShell = ComPtr!(IVsUIShell)(queryService!(IVsUIShell), false); if(!pIVsUIShell) return false; - sSearchPane = newCom!SearchPane; const(wchar)* caption = "Visual D Search"w.ptr; HRESULT hr; hr = pIVsUIShell.CreateToolWindow(CTW_fInitNew, 0, sSearchPane, &GUID_NULL, &g_searchWinCLSID, &GUID_NULL, null, caption, null, &sWindowFrame); if(!SUCCEEDED(hr)) - { - sSearchPane = null; return false; - } } + if(FAILED(sWindowFrame.Show())) return false; BOOL fHandled; @@ -210,13 +217,17 @@ class SearchWindowBack : Window class SearchPane : DisposingComObject, IVsWindowPane { + static const GUID iid = uuid("FFA501E1-0565-4621-ADEA-9A8F10C1805B"); + IServiceProvider mSite; override HRESULT QueryInterface(in IID* riid, void** pvObject) { + if(queryInterface!(SearchPane) (this, riid, pvObject)) + return S_OK; if(queryInterface!(IVsWindowPane) (this, riid, pvObject)) return S_OK; - + // avoid debug output if(*riid == IVsCodeWindow.iid || *riid == IServiceProvider.iid || *riid == IVsTextView.iid) return E_NOINTERFACE; @@ -264,6 +275,8 @@ class SearchPane : DisposingComObject, IVsWindowPane mixin(LogCallMix2); if(_wndParent) { + _WriteViewStateToRegistry(); + _wndParent.Dispose(); _wndParent = null; _wndBack = null; @@ -282,13 +295,82 @@ class SearchPane : DisposingComObject, IVsWindowPane HRESULT LoadViewState(/+[in]+/ IStream pstream) { mixin(LogCallMix2); - return returnError(E_NOTIMPL); + if(!pstream) + return E_INVALIDARG; + + HRESULT _doRead(void* p, size_t cnt) + { + uint read; + HRESULT hr = pstream.Read(cast(byte*)p, cnt, &read); + if(FAILED(hr)) + return hr; + if(read != cnt) + return E_UNEXPECTED; + return hr; + } + + HRESULT _doReadColumn(ref COLUMNINFO[] columns) + { + uint num; + if(HRESULT hr = _doRead(cast(byte*)&num, num.sizeof)) + return hr; + if(num > 10) + return E_UNEXPECTED; + columns.length = num; + if(HRESULT hr = _doRead(columns.ptr, columns.length * COLUMNINFO.sizeof)) + return hr; + return S_OK; + } + + uint size; + if(HRESULT hr = _doRead(cast(byte*)&size, size.sizeof)) + return hr; + if(HRESULT hr = _doReadColumn(_fileColumns)) + return hr; + if(HRESULT hr = _doReadColumn(_symbolColumns)) + return hr; + return S_OK; } + HRESULT SaveViewState(/+[in]+/ IStream pstream) { mixin(LogCallMix2); - return returnError(E_NOTIMPL); + if(!pstream) + return E_INVALIDARG; + + HRESULT _doWrite(const(void)* p, size_t cnt) + { + uint written; + HRESULT hr = pstream.Write(cast(const(byte)*)p, cnt, &written); + if(FAILED(hr)) + return hr; + if(written != cnt) + return E_UNEXPECTED; + return hr; + } + + HRESULT _doWriteColumn(COLUMNINFO[] columns) + { + uint num = columns.length; + if(HRESULT hr = _doWrite(cast(byte*)&num, num.sizeof)) + return hr; + if(HRESULT hr = _doWrite(columns.ptr, columns.length * COLUMNINFO.sizeof)) + return hr; + return S_OK; + } + + // write size overall to allow skipping chunk + uint size = 2 * uint.sizeof + (_fileColumns.length + _symbolColumns.length) * COLUMNINFO.sizeof; + if(HRESULT hr = _doWrite(cast(byte*)&size, size.sizeof)) + return hr; + + if(HRESULT hr = _doWriteColumn(_fileColumns)) + return hr; + if(HRESULT hr = _doWriteColumn(_symbolColumns)) + return hr; + return S_OK; } + HRESULT TranslateAccelerator(MSG* msg) { if(msg.message == WM_TIMER) @@ -469,7 +551,7 @@ private: _wndFileList.SendMessage(LVM_DELETEALLITEMS); _wndFileList.SendMessage(LVM_REMOVEALLGROUPS); - HIMAGELIST himl = LoadImageList(getInstance(), kImageBmp.ptr, 16, 16); + HIMAGELIST himl = LoadImageList(getInstance(), MAKEINTRESOURCEA(BMP_DIMAGELIST), 16, 16); if(himl) _wndFileList.SendMessage(LVM_SETIMAGELIST, LVSIL_SMALL, cast(LPARAM)himl); @@ -1593,7 +1675,7 @@ else try { scope RegKey keyWinOpts = _GetCurrentRegKey(false); - if(keyWinOpts.GetDWORD("ColumnInfoVersion"w, 0) == 1) + if(keyWinOpts.GetDWORD("ColumnInfoVersion"w, 0) == kColumnInfoVersion) { void[] data = keyWinOpts.GetBinary("ColumnInfo"w); if(data !is null) diff --git a/visuald/viewfilter.d b/visuald/viewfilter.d index 84bc58d0..665cae73 100644 --- a/visuald/viewfilter.d +++ b/visuald/viewfilter.d @@ -595,7 +595,7 @@ version(tip) release(cfg); } if (disasm && symdebug == 0) // ensure debug info is enabled - cfg.GetProjectOptions().symdebug = 2; + cfg.GetProjectOptions().symdebug = 3; string stool = cfg.GetStaticCompileTool(pFile, cfg.getCfgName()); if(stool == "DMD") diff --git a/visuald/visuald.visualdproj b/visuald/visuald.visualdproj index 25c81203..24d44769 100644 --- a/visuald/visuald.visualdproj +++ b/visuald/visuald.visualdproj @@ -184,7 +184,7 @@ 0 1 - m:\s\d\cv2pdb\trunk\bin\debug\cv2pdb.exe + $(VisualDInstallDir)\cv2pdb\cv2pdb.exe 0 0 0 @@ -552,22 +552,20 @@ - diff --git a/visuald/winctrl.d b/visuald/winctrl.d index d12dbf30..819ab70c 100644 --- a/visuald/winctrl.d +++ b/visuald/winctrl.d @@ -9,10 +9,12 @@ module visuald.winctrl; import visuald.windows; +import visuald.logutil; import std.utf; import std.string; import std.array; import std.exception; +import std.algorithm; import sdk.port.base; import sdk.win32.prsht; import sdk.win32.commctrl; @@ -166,26 +168,26 @@ class Widget assert(ok, "Failed to move window in setRect"); } - void setVisible(bool visible) + void setVisible(bool visible) { ShowWindow(hwnd, visible ? SW_SHOW : SW_HIDE); // ignore bool result } - void setEnabled(bool enable) + void setEnabled(bool enable) { EnableWindow(hwnd, enable); } - - void SetFocus() + + void SetFocus() { .SetFocus(hwnd); } - - void SetRedraw(bool enable) + + void SetRedraw(bool enable) { SendMessage(WM_SETREDRAW, enable); } - + int SendMessage(int msg, WPARAM wp = 0, LPARAM lp = 0) { return .SendMessage(hwnd, msg, wp, lp); @@ -195,8 +197,8 @@ class Widget { .InvalidateRect(hwnd, r, erase); } - - string GetWindowText() + + string GetWindowText() { WCHAR[256] txt; int len = GetWindowTextW(hwnd, txt.ptr, txt.length); @@ -207,26 +209,26 @@ class Widget len = GetWindowTextW(hwnd, buffer.ptr, len+1); return toUTF8(buffer[0..len]); } - bool SetWindowText(string txt) + bool SetWindowText(string txt) { return SetWindowTextW(hwnd, toUTF16z(txt)) != 0; } - + bool GetWindowRect(RECT* r) { return .GetWindowRect(hwnd, r) != 0; } - + bool GetClientRect(RECT* r) { return .GetClientRect(hwnd, r) != 0; } - + bool ScreenToClient(POINT *lpPoint) { return .ScreenToClient(hwnd, lpPoint) != 0; } - + bool ScreenToClient(RECT *rect) { POINT pnt = { rect.left, rect.top }; @@ -238,7 +240,7 @@ class Widget rect.top = pnt.y; return true; } - + bool SetWindowPos(HWND hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags) { return .SetWindowPos(hwnd, hWndInsertAfter, X, Y, cx, cy, uFlags) != 0; @@ -249,47 +251,47 @@ class Widget return .SetWindowPos(hwnd, hWndInsertAfter, r.left, r.top, r.right - r.left, r.bottom - r.top, uFlags) != 0; } - bool SetWindowStyle(int style) + bool SetWindowStyle(int style) { return SetWindowLongA(hwnd, GWL_STYLE, style) != 0; } - bool AddWindowStyle(int flag, int clear = 0) + bool AddWindowStyle(int flag, int clear = 0) { DWORD style = GetWindowLongA(hwnd, GWL_STYLE); return SetWindowLongA(hwnd, GWL_STYLE, (style & ~clear) | flag) != 0; } - bool DelWindowStyle(int flag) + bool DelWindowStyle(int flag) { DWORD style = GetWindowLongA(hwnd, GWL_STYLE); return SetWindowLongA(hwnd, GWL_STYLE, style & ~flag) != 0; } - bool SetWindowExStyle(int style) + bool SetWindowExStyle(int style) { return SetWindowLongA(hwnd, GWL_EXSTYLE, style) != 0; } - bool AddWindowExStyle(int flag, int clear = 0) + bool AddWindowExStyle(int flag, int clear = 0) { DWORD style = GetWindowLongA(hwnd, GWL_EXSTYLE); return SetWindowLongA(hwnd, GWL_EXSTYLE, (style & ~clear) | flag) != 0; } - bool DelWindowExStyle(int flag) + bool DelWindowExStyle(int flag) { DWORD style = GetWindowLongA(hwnd, GWL_EXSTYLE); return SetWindowLongA(hwnd, GWL_EXSTYLE, style & ~flag) != 0; } - static Widget fromHWND(HWND hwnd) + static Widget fromHWND(HWND hwnd) { return cast(Widget)cast(void*)GetWindowLongA(hwnd, GWL_USERDATA); } static HINSTANCE getInstance() { return hInst; } - + } class Window : Widget @@ -297,12 +299,12 @@ class Window : Widget static bool hasRegistered = false; static HBRUSH bgbrush; - static void registerClass() + static void registerClass() { if(hasRegistered) return; hasRegistered = true; - + DWORD color = GetSysColor(COLOR_BTNFACE); bgbrush = CreateSolidBrush(color); @@ -321,7 +323,7 @@ class Window : Widget ATOM atom = RegisterClassA(&wc); assert(atom); } - static void unregisterClass() + static void unregisterClass() { if(!hasRegistered) return; @@ -379,7 +381,7 @@ class Window : Widget return DefWindowProcA(hWnd, uMsg, wParam, lParam); } - int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) + int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_COMMAND: @@ -452,12 +454,12 @@ class Dialog : Widget static bool hasRegistered = false; static HBRUSH bgbrush; - static void registerClass() + static void registerClass() { if(hasRegistered) return; hasRegistered = true; - + DWORD color = GetSysColor(COLOR_BTNFACE); bgbrush = CreateSolidBrush(color); @@ -476,7 +478,7 @@ class Dialog : Widget ATOM atom = RegisterClassA(&wc); assert(atom); } - static void unregisterClass() + static void unregisterClass() { if(!hasRegistered) return; @@ -506,7 +508,7 @@ class Dialog : Widget super(parent); } - int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) + int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) { return DefDlgProcA(hWnd, uMsg, wParam, lParam); } @@ -564,7 +566,7 @@ class Text : Widget SendMessageW(hwnd, WM_SETTEXT, 0, cast(LPARAM)winstr.ptr); } - string getText() + string getText() { int len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0); scope buffer = new wchar[len+1]; @@ -574,7 +576,7 @@ class Text : Widget return s; } - wstring getWText() + wstring getWText() { int len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0); auto buffer = new wchar[len+1]; @@ -616,7 +618,7 @@ class MultiLineText : Text return hWnd; } - int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) + int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) { if(uMsg == WM_CHAR) { @@ -637,7 +639,7 @@ class MultiLineText : Text class ComboBox : Widget { - this(Widget parent, string[] texts, bool editable = true, int id = 0) + this(Widget parent, string[] texts, bool editable = true, int id = 0) { HWND parenthwnd = parent ? parent.hwnd : null; DWORD style = editable ? CBS_DROPDOWN | CBS_AUTOHSCROLL : CBS_DROPDOWNLIST; @@ -650,30 +652,30 @@ class ComboBox : Widget super(parent); } - int findString(string s) + int findString(string s) { return SendMessageW(hwnd, CB_FINDSTRING, 0, cast(LPARAM)toUTF16z(s)); } - int getSelection() + int getSelection() { return SendMessageA(hwnd, CB_GETCURSEL, 0, 0); } - void setSelection(int n) + void setSelection(int n) { SendMessageA(hwnd, CB_SETCURSEL, n, 0); } - void setSelection(string s) + void setSelection(string s) { SendMessageA(hwnd, CB_SELECTSTRING, 0, cast(LPARAM)toUTF16z(s)); } - string getText() + string getText() { int len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0); scope buffer = new wchar[len+1]; SendMessageW(hwnd, WM_GETTEXT, cast(WPARAM)(len+1), cast(LPARAM)buffer.ptr); return toUTF8(buffer[0..$-1]); } - wstring getWText() + wstring getWText() { int len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0); scope buffer = new wchar[len+1]; @@ -685,13 +687,13 @@ class ComboBox : Widget class ButtonBase : Widget { this(Widget parent) { super(parent); } - - bool isChecked() + + bool isChecked() { bool res = SendMessageA(hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED; return res; } - void setChecked(bool x) + void setChecked(bool x) { SendMessageA(hwnd, BM_SETCHECK, x ? BST_CHECKED : BST_UNCHECKED, 0); } @@ -699,7 +701,7 @@ class ButtonBase : Widget class CheckBox : ButtonBase { - this(Widget parent, string intext, int id = 0) + this(Widget parent, string intext, int id = 0) { HWND parenthwnd = parent ? parent.hwnd : null; createWidget(parent, "BUTTON", intext, BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, id); @@ -710,7 +712,7 @@ class CheckBox : ButtonBase class Button : ButtonBase { - this(Widget parent, string intext, int id = 0) + this(Widget parent, string intext, int id = 0) { HWND parenthwnd = parent ? parent.hwnd : null; createWidget(parent, "BUTTON", intext, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, id); @@ -721,7 +723,7 @@ class Button : ButtonBase class Frame : ButtonBase { - this(Widget parent, string intext = "", int id = 0) + this(Widget parent, string intext = "", int id = 0) { HWND parenthwnd = parent ? parent.hwnd : null; createWidget(parent, "BUTTON", intext, BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 0, id); @@ -732,13 +734,13 @@ class Frame : ButtonBase class ToolBar : Widget { - this(Widget parent, uint style, uint exstyle, int id = 0) + this(Widget parent, uint style, uint exstyle, int id = 0) { HWND parenthwnd = parent ? parent.hwnd : null; createWidget(parent, TOOLBARCLASSNAMEA, "", style | WS_CHILD | WS_VISIBLE, exstyle, id); super(parent); } - + bool EnableCheckButton(uint id, bool enable, bool check) { TBBUTTONINFO tbi; @@ -746,14 +748,14 @@ class ToolBar : Widget tbi.dwMask = TBIF_STATE; tbi.fsState = (enable ? TBSTATE_ENABLED : 0) | (check ? TBSTATE_CHECKED : 0); - + return .SendMessage(hwnd, TB_SETBUTTONINFO, id, cast(LPARAM)&tbi) != 0; } } class ListView : Widget { - this(Widget parent, uint style, uint exstyle, int id = 0) + this(Widget parent, uint style, uint exstyle, int id = 0) { HWND parenthwnd = parent ? parent.hwnd : null; createWidget(parent, "SysListView32", "", style | WS_CHILD | WS_VISIBLE | WS_TABSTOP, exstyle, id); @@ -768,7 +770,7 @@ class ListView : Widget class TabControl : Widget { - this(Widget parent, string[] tabs, uint style = 0, uint exstyle = 0, int id = 0) + this(Widget parent, string[] tabs, uint style = 0, uint exstyle = 0, int id = 0) { HWND parenthwnd = parent ? parent.hwnd : null; createWidget(parent, "SysTabControl32", "", style | WS_CHILD | WS_VISIBLE | WS_TABSTOP, exstyle, id); @@ -828,6 +830,32 @@ class TabControl : Widget setPageSize(left, top, w, h); } + override bool GetWindowRect(RECT* rect) + { + if(!super.GetWindowRect(rect)) + return false; + if(!pages.empty) + { + RECT pr; + if (!pages[0].GetWindowRect(&pr)) + return false; + rect.bottom = pr.bottom; + } + return true; + } + + // space for header and footer + int getFrameHeight() + { + RECT r; + r.left = 0; + r.right = 100; + r.top = 0; + r.bottom = 100; + SendMessage(TCM_ADJUSTRECT, false, cast(LPARAM)&r); + return r.top + (100 - r.bottom); + } + int getCurSel() { return SendMessage(TCM_GETCURSEL, 0, 0); @@ -848,12 +876,12 @@ int PopupContextMenu(HWND hwnd, POINT pt, wstring[] entries, int check = -1, int if(!hmnu) return -1; scope(exit) DestroyMenu(hmnu); - + MENUITEMINFO mii; mii.cbSize = mii.sizeof; mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE | MIIM_STRING; mii.fType = MFT_STRING; - + wchar*[] entriesz; for (int i = 0; i < entries.length; i++) { @@ -875,6 +903,76 @@ int PopupContextMenu(HWND hwnd, POINT pt, wstring[] entries, int check = -1, int return -1; } +struct Attachment +{ + // specify the fraction that the control receives from a size change + short hdiv; + short left; // left edge will receive left/hdiv of change + short right; + short vdiv; + short top; + short bottom; +} + +enum kAttachNone = Attachment(1, 0, 0, 1, 0, 0); +enum kAttachLeftRight = Attachment(1, 0, 1, 1, 0, 0); +enum kAttachRight = Attachment(1, 1, 1, 1, 0, 0); +enum kAttachTopBottom = Attachment(1, 0, 0, 1, 0, 1); +enum kAttachBottom = Attachment(1, 0, 0, 1, 1, 1); +enum kAttachAll = Attachment(1, 0, 1, 1, 0, 1); + +struct AttachData +{ + Attachment att; + short initleft; // initial rect of child window relative to parent + short initright; + short inittop; + short initbottom; + short initwidth; // initial parent width + short initheight; // initial parent height + + bool initFromWidget(Widget w) + { + RECT r, pr; + if (!w.GetWindowRect(&r)) + return false; + if (!w.parent || !w.parent.GetWindowRect(&pr)) + return false; + + initwidth = cast(short) (pr.right - pr.left); + initheight = cast(short) (pr.bottom - pr.top); + initleft = cast(short) (r.left - pr.left); + initright = cast(short) (r.right - pr.left); + inittop = cast(short) (r.top - pr.top); + initbottom = cast(short) (r.bottom - pr.top); + + //logCall("initFromWidget(", w, ":", cast(void*)w, ") = w:", initwidth, " h:", initheight, " l:", initleft, " r:", initright, " t:", inittop, " b:", initbottom); + return true; + } + + bool resizeWidget(Widget w) + { + RECT pr; + if (!w.parent || !w.parent.GetWindowRect(&pr)) + return false; + + int dx = pr.right - pr.left - initwidth; + int dy = pr.bottom - pr.top - initheight; + int hdiv = max(1, att.hdiv); + int vdiv = max(1, att.vdiv); + + int nleft = initleft + dx * att.left / hdiv; + int nright = initright + dx * att.right / hdiv; + int ntop = inittop + dy * att.top / vdiv; + int nbottom = initbottom + dy * att.bottom / vdiv; + + //logCall("resizeWidget(", w, ":", cast(void*)w, ") to [l:", nleft, " t:", ntop, " w:", nright - nleft, " h:", nbottom - ntop, "]"); + + w.setRect(nleft, ntop, nright - nleft, nbottom - ntop); + return true; + } +} + bool initWinControls(HINSTANCE inst) { hInst = inst;