From 56ac20f3051081368c92e21071989ffc5042c9d7 Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Wed, 12 Sep 2007 15:00:16 +0200 Subject: [PATCH] push b72af2511d67bded8ece08d825ff0eb4a60c20a6 --- dlls/advapi32/service.c | 61 +- dlls/crypt32/chain.c | 146 ++++- dlls/crypt32/crypt32.spec | 5 +- dlls/crypt32/main.c | 19 +- dlls/crypt32/rootstore.c | 1 + dlls/crypt32/tests/chain.c | 42 +- dlls/d3d9/tests/texture.c | 68 ++ dlls/d3d9/tests/visual.c | 110 ++++ dlls/dmband/regsvr.c | 76 +-- dlls/dmcompos/regsvr.c | 76 +-- dlls/gdi32/freetype.c | 2 +- dlls/kernel32/tests/comm.c | 12 +- dlls/mshtml/En.rc | 14 + dlls/mshtml/editor.c | 230 ++++++- dlls/mshtml/mshtml_private.h | 4 +- dlls/mshtml/nsembed.c | 36 +- dlls/mshtml/nsiface.idl | 160 ++++- dlls/mshtml/persist.c | 2 +- dlls/mshtml/resource.h | 6 + dlls/ole32/compobj.c | 84 ++- dlls/ole32/ole32.spec | 1 + dlls/rpcrt4/rpc_message.c | 5 +- dlls/rsaenh/rsaenh.c | 11 +- dlls/setupapi/stringtable.c | 4 +- dlls/shell32/pidl.c | 8 +- dlls/shell32/pidl.h | 4 +- dlls/shell32/shell.c | 2 +- dlls/shell32/shlfolder.c | 101 +-- dlls/winealsa.drv/dscapture.c | 237 ++++++- dlls/wined3d/baseshader.c | 7 +- dlls/wined3d/basetexture.c | 38 ++ dlls/wined3d/device.c | 36 +- dlls/wined3d/directx.c | 25 +- dlls/wined3d/glsl_shader.c | 39 +- dlls/wined3d/pixelshader.c | 2 +- dlls/wined3d/state.c | 50 +- dlls/wined3d/surface.c | 96 ++- dlls/wined3d/utils.c | 2 +- dlls/wined3d/wined3d_private.h | 3 +- dlls/winex11.drv/opengl.c | 61 +- dlls/wintrust/softpub.c | 71 +- dlls/wintrust/tests/asn.c | 40 +- dlls/wintrust/tests/softpub.c | 8 +- dlls/wldap32/wldap32_Fr.rc | 2 +- include/Makefile.in | 1 + include/i_cryptasn1tls.h | 41 ++ include/objbase.h | 1 + include/wine/wined3d_gl.h | 14 +- programs/cmd/batch.c | 48 +- programs/cmd/builtins.c | 308 ++++++--- programs/cmd/directory.c | 1 + programs/cmd/wcmd.h | 8 +- programs/cmd/wcmdmain.c | 572 +++++++++++------ programs/wordpad/De.rc | 111 +++- programs/wordpad/En.rc | 111 +++- programs/wordpad/Fr.rc | 111 +++- programs/wordpad/Hu.rc | 111 +++- programs/wordpad/Ko.rc | 111 +++- programs/wordpad/Nl.rc | 111 +++- programs/wordpad/No.rc | 111 +++- programs/wordpad/Pl.rc | 111 +++- programs/wordpad/Ru.rc | 112 +++- programs/wordpad/Tr.rc | 112 +++- programs/wordpad/resource.h | 70 +- programs/wordpad/rsrc.rc | 1 + programs/wordpad/wordpad.c | 1394 ++++++++++++++++++++++++++++++++++++---- tools/winapi/win32.api | 17 +- 67 files changed, 4592 insertions(+), 1003 deletions(-) create mode 100644 include/i_cryptasn1tls.h diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index fbc888dbf9e..a698f116b1e 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -197,7 +197,9 @@ static void sc_handle_destroy_service(struct sc_handle *handle) } /****************************************************************************** - * String management functions + * String management functions (same behaviour as strdup) + * NOTE: the caller of those functions is responsible for calling HeapFree + * in order to release the memory allocated by those functions. */ static inline LPWSTR SERV_dup( LPCSTR str ) { @@ -231,11 +233,6 @@ static inline LPWSTR SERV_dupmulti(LPCSTR str) return wstr; } -static inline VOID SERV_free( LPWSTR wstr ) -{ - HeapFree( GetProcessHeap(), 0, wstr ); -} - /****************************************************************************** * registry access functions and data */ @@ -345,7 +342,7 @@ static HANDLE service_open_pipe(LPCWSTR service) if (GetLastError() != ERROR_PIPE_BUSY) break; } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER)); - SERV_free(szPipe); + HeapFree(GetProcessHeap(), 0, szPipe); return handle; } @@ -366,7 +363,7 @@ static HANDLE service_get_event_handle(LPCWSTR service) strcpyW(name, prefix); strcatW(name, service); handle = CreateEventW(NULL, TRUE, FALSE, name); - SERV_free(name); + HeapFree(GetProcessHeap(), 0, name); return handle; } @@ -458,7 +455,7 @@ static BOOL service_handle_start(HANDLE pipe, service_data *service, DWORD count goto end; } - SERV_free(service->args); + HeapFree(GetProcessHeap(), 0, service->args); service->args = args; args = NULL; service->thread = CreateThread( NULL, 0, service_thread, @@ -688,7 +685,7 @@ static DWORD WINAPI service_control_dispatcher(LPVOID arg) name = service_get_pipe_name(service->name); pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_WAIT, 1, 256, 256, 10000, NULL ); - SERV_free(name); + HeapFree(GetProcessHeap(), 0, name); /* let the process who started us know we've tried to create a pipe */ event = service_get_event_handle(service->name); @@ -921,7 +918,7 @@ RegisterServiceCtrlHandlerA( LPCSTR lpServiceName, LPHANDLER_FUNCTION lpfHandler lpServiceNameW = SERV_dup(lpServiceName); ret = RegisterServiceCtrlHandlerW( lpServiceNameW, lpfHandler ); - SERV_free(lpServiceNameW); + HeapFree(GetProcessHeap(), 0, lpServiceNameW); return ret; } @@ -1011,8 +1008,8 @@ SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName, lpMachineNameW = SERV_dup(lpMachineName); lpDatabaseNameW = SERV_dup(lpDatabaseName); ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess); - SERV_free(lpDatabaseNameW); - SERV_free(lpMachineNameW); + HeapFree(GetProcessHeap(), 0, lpDatabaseNameW); + HeapFree(GetProcessHeap(), 0, lpMachineNameW); return ret; } @@ -1195,7 +1192,7 @@ SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName, lpServiceNameW = SERV_dup(lpServiceName); ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess); - SERV_free(lpServiceNameW); + HeapFree(GetProcessHeap(), 0, lpServiceNameW); return ret; } @@ -1494,13 +1491,13 @@ CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName, lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId, lpDependenciesW, lpServiceStartNameW, lpPasswordW ); - SERV_free( lpServiceNameW ); - SERV_free( lpDisplayNameW ); - SERV_free( lpBinaryPathNameW ); - SERV_free( lpLoadOrderGroupW ); - SERV_free( lpDependenciesW ); - SERV_free( lpServiceStartNameW ); - SERV_free( lpPasswordW ); + HeapFree( GetProcessHeap(), 0, lpServiceNameW ); + HeapFree( GetProcessHeap(), 0, lpDisplayNameW ); + HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW ); + HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW ); + HeapFree( GetProcessHeap(), 0, lpDependenciesW ); + HeapFree( GetProcessHeap(), 0, lpServiceStartNameW ); + HeapFree( GetProcessHeap(), 0, lpPasswordW ); return r; } @@ -1591,7 +1588,7 @@ BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs, if (dwNumServiceArgs) { for(i=0; i +#define NONAMELESSUNION #include "windef.h" #include "winbase.h" #include "wincrypt.h" @@ -178,7 +179,7 @@ BOOL WINAPI CertCreateCertificateChainEngine(PCERT_CHAIN_ENGINE_CONFIG pConfig, return ret; } -void WINAPI CertFreeCertificateChainEngine(HCERTCHAINENGINE hChainEngine) +VOID WINAPI CertFreeCertificateChainEngine(HCERTCHAINENGINE hChainEngine) { PCertificateChainEngine engine = (PCertificateChainEngine)hChainEngine; @@ -278,7 +279,7 @@ static inline void CRYPT_CombineTrustStatus(CERT_TRUST_STATUS *chainStatus, } static BOOL CRYPT_AddCertToSimpleChain(PCertificateChainEngine engine, - PCERT_SIMPLE_CHAIN chain, PCCERT_CONTEXT cert) + PCERT_SIMPLE_CHAIN chain, PCCERT_CONTEXT cert, DWORD subjectInfoStatus) { BOOL ret = FALSE; PCERT_CHAIN_ELEMENT element = CryptMemAlloc(sizeof(CERT_CHAIN_ELEMENT)); @@ -296,6 +297,9 @@ static BOOL CRYPT_AddCertToSimpleChain(PCertificateChainEngine engine, memset(element, 0, sizeof(CERT_CHAIN_ELEMENT)); element->cbSize = sizeof(CERT_CHAIN_ELEMENT); element->pCertContext = CertDuplicateCertificateContext(cert); + if (chain->cElement > 1) + chain->rgpElement[chain->cElement - 2]->TrustStatus.dwInfoStatus + = subjectInfoStatus; /* FIXME: initialize the rest of element */ if (chain->cElement % engine->CycleDetectionModulus) CRYPT_CheckSimpleChainForCycles(chain); @@ -504,13 +508,129 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine, } if (CRYPT_IsCertificateSelfSigned(rootElement->pCertContext)) { - rootElement->TrustStatus.dwInfoStatus |= CERT_TRUST_IS_SELF_SIGNED; + rootElement->TrustStatus.dwInfoStatus |= + CERT_TRUST_IS_SELF_SIGNED | CERT_TRUST_HAS_NAME_MATCH_ISSUER; CRYPT_CheckRootCert(engine->hRoot, rootElement); } /* FIXME: check revocation of every cert with CertVerifyRevocation */ CRYPT_CombineTrustStatus(&chain->TrustStatus, &rootElement->TrustStatus); } +static PCCERT_CONTEXT CRYPT_GetIssuer(HCERTSTORE store, PCCERT_CONTEXT subject, + PCCERT_CONTEXT prevIssuer, DWORD *infoStatus) +{ + PCCERT_CONTEXT issuer = NULL; + PCERT_EXTENSION ext; + DWORD size; + + *infoStatus = 0; + if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER, + subject->pCertInfo->cExtension, subject->pCertInfo->rgExtension))) + { + CERT_AUTHORITY_KEY_ID_INFO *info; + BOOL ret; + + ret = CryptDecodeObjectEx(subject->dwCertEncodingType, + X509_AUTHORITY_KEY_ID, ext->Value.pbData, ext->Value.cbData, + CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, + &info, &size); + if (ret) + { + CERT_ID id; + + if (info->CertIssuer.cbData && info->CertSerialNumber.cbData) + { + id.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; + memcpy(&id.u.IssuerSerialNumber.Issuer, &info->CertIssuer, + sizeof(CERT_NAME_BLOB)); + memcpy(&id.u.IssuerSerialNumber.SerialNumber, + &info->CertSerialNumber, sizeof(CRYPT_INTEGER_BLOB)); + issuer = CertFindCertificateInStore(store, + subject->dwCertEncodingType, 0, CERT_FIND_CERT_ID, &id, + prevIssuer); + if (issuer) + *infoStatus = CERT_TRUST_HAS_EXACT_MATCH_ISSUER; + } + else if (info->KeyId.cbData) + { + id.dwIdChoice = CERT_ID_KEY_IDENTIFIER; + memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB)); + issuer = CertFindCertificateInStore(store, + subject->dwCertEncodingType, 0, CERT_FIND_CERT_ID, &id, + prevIssuer); + if (issuer) + *infoStatus = CERT_TRUST_HAS_KEY_MATCH_ISSUER; + } + LocalFree(info); + } + } + else if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2, + subject->pCertInfo->cExtension, subject->pCertInfo->rgExtension))) + { + CERT_AUTHORITY_KEY_ID2_INFO *info; + BOOL ret; + + ret = CryptDecodeObjectEx(subject->dwCertEncodingType, + X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData, + CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, + &info, &size); + if (ret) + { + CERT_ID id; + + if (info->AuthorityCertIssuer.cAltEntry && + info->AuthorityCertSerialNumber.cbData) + { + PCERT_ALT_NAME_ENTRY directoryName = NULL; + DWORD i; + + for (i = 0; !directoryName && + i < info->AuthorityCertIssuer.cAltEntry; i++) + if (info->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice + == CERT_ALT_NAME_DIRECTORY_NAME) + directoryName = + &info->AuthorityCertIssuer.rgAltEntry[i]; + if (directoryName) + { + id.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; + memcpy(&id.u.IssuerSerialNumber.Issuer, + &directoryName->u.DirectoryName, sizeof(CERT_NAME_BLOB)); + memcpy(&id.u.IssuerSerialNumber.SerialNumber, + &info->AuthorityCertSerialNumber, + sizeof(CRYPT_INTEGER_BLOB)); + issuer = CertFindCertificateInStore(store, + subject->dwCertEncodingType, 0, CERT_FIND_CERT_ID, &id, + prevIssuer); + if (issuer) + *infoStatus = CERT_TRUST_HAS_EXACT_MATCH_ISSUER; + } + else + FIXME("no supported name type in authority key id2\n"); + } + else if (info->KeyId.cbData) + { + id.dwIdChoice = CERT_ID_KEY_IDENTIFIER; + memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB)); + issuer = CertFindCertificateInStore(store, + subject->dwCertEncodingType, 0, CERT_FIND_CERT_ID, &id, + prevIssuer); + if (issuer) + *infoStatus = CERT_TRUST_HAS_KEY_MATCH_ISSUER; + } + LocalFree(info); + } + } + else + { + issuer = CertFindCertificateInStore(store, + subject->dwCertEncodingType, 0, CERT_FIND_SUBJECT_NAME, + &subject->pCertInfo->Issuer, prevIssuer); + if (issuer) + *infoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER; + } + return issuer; +} + /* Builds a simple chain by finding an issuer for the last cert in the chain, * until reaching a self-signed cert, or until no issuer can be found. */ @@ -523,13 +643,12 @@ static BOOL CRYPT_BuildSimpleChain(PCertificateChainEngine engine, while (ret && !CRYPT_IsSimpleChainCyclic(chain) && !CRYPT_IsCertificateSelfSigned(cert)) { - DWORD flags = 0; - PCCERT_CONTEXT issuer = - CertGetIssuerCertificateFromStore(world, cert, NULL, &flags); + DWORD infoStatus; + PCCERT_CONTEXT issuer = CRYPT_GetIssuer(world, cert, NULL, &infoStatus); if (issuer) { - ret = CRYPT_AddCertToSimpleChain(engine, chain, issuer); + ret = CRYPT_AddCertToSimpleChain(engine, chain, issuer, infoStatus); cert = issuer; } else @@ -555,7 +674,7 @@ static BOOL CRYPT_GetSimpleChainForCert(PCertificateChainEngine engine, { memset(chain, 0, sizeof(CERT_SIMPLE_CHAIN)); chain->cbSize = sizeof(CERT_SIMPLE_CHAIN); - ret = CRYPT_AddCertToSimpleChain(engine, chain, cert); + ret = CRYPT_AddCertToSimpleChain(engine, chain, cert, 0); if (ret) { ret = CRYPT_BuildSimpleChain(engine, world, chain); @@ -782,7 +901,7 @@ static PCertificateChain CRYPT_BuildAlternateContextFromChain( alternate = NULL; else { - DWORD i, j, flags; + DWORD i, j, infoStatus; PCCERT_CONTEXT alternateIssuer = NULL; alternate = NULL; @@ -795,9 +914,8 @@ static PCertificateChain CRYPT_BuildAlternateContextFromChain( PCCERT_CONTEXT prevIssuer = CertDuplicateCertificateContext( chain->context.rgpChain[i]->rgpElement[j + 1]->pCertContext); - flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG; - alternateIssuer = CertGetIssuerCertificateFromStore( - prevIssuer->hCertStore, subject, prevIssuer, &flags); + alternateIssuer = CRYPT_GetIssuer(prevIssuer->hCertStore, + subject, prevIssuer, &infoStatus); } if (alternateIssuer) { @@ -807,7 +925,7 @@ static PCertificateChain CRYPT_BuildAlternateContextFromChain( if (alternate) { BOOL ret = CRYPT_AddCertToSimpleChain(engine, - alternate->context.rgpChain[i], alternateIssuer); + alternate->context.rgpChain[i], alternateIssuer, infoStatus); if (ret) { @@ -1008,7 +1126,7 @@ PCCERT_CHAIN_CONTEXT WINAPI CertDuplicateCertificateChain( return pChainContext; } -void WINAPI CertFreeCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext) +VOID WINAPI CertFreeCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext) { PCertificateChain chain = (PCertificateChain)pChainContext; diff --git a/dlls/crypt32/crypt32.spec b/dlls/crypt32/crypt32.spec index ac706c7646d..cbadf229284 100644 --- a/dlls/crypt32/crypt32.spec +++ b/dlls/crypt32/crypt32.spec @@ -199,17 +199,18 @@ @ stdcall I_CryptFreeLruCache(ptr long long) @ stdcall I_CryptFreeTls(long long) @ stdcall I_CryptGetAsn1Decoder(long) +@ stdcall I_CryptGetAsn1Encoder(long) @ stdcall I_CryptGetDefaultCryptProv(long) @ stub I_CryptGetDefaultCryptProvForEncrypt @ stdcall I_CryptGetOssGlobal(long) @ stdcall I_CryptGetTls(long) @ stub I_CryptInsertLruEntry -@ stdcall I_CryptInstallAsn1Module(long long long) +@ stdcall I_CryptInstallAsn1Module(ptr long ptr) @ stdcall I_CryptInstallOssGlobal(long long long) @ stdcall I_CryptReadTrustedPublisherDWORDValueFromRegistry(wstr ptr) @ stub I_CryptReleaseLruEntry @ stdcall I_CryptSetTls(long ptr) -@ stdcall I_CryptUninstallAsn1Module(ptr) +@ stdcall I_CryptUninstallAsn1Module(long) @ stub I_CryptUninstallOssGlobal @ stub PFXExportCertStore @ stub PFXImportCertStore diff --git a/dlls/crypt32/main.c b/dlls/crypt32/main.c index 9e53e4b5307..db1744720de 100644 --- a/dlls/crypt32/main.c +++ b/dlls/crypt32/main.c @@ -26,6 +26,7 @@ #include "wincrypt.h" #include "winreg.h" #include "winuser.h" +#include "i_cryptasn1tls.h" #include "crypt32_private.h" #include "wine/debug.h" @@ -195,21 +196,27 @@ DWORD WINAPI I_CryptInstallOssGlobal(DWORD x, DWORD y, DWORD z) return ret; } -BOOL WINAPI I_CryptInstallAsn1Module(void *x, DWORD y, DWORD z) +BOOL WINAPI I_CryptInstallAsn1Module(ASN1module_t x, DWORD y, void* z) { - FIXME("%p %08x %08x\n", x, y, z); + FIXME("(%p %08x %p): stub\n", x, y, z); return TRUE; } -BOOL WINAPI I_CryptUninstallAsn1Module(void *x) +BOOL WINAPI I_CryptUninstallAsn1Module(HCRYPTASN1MODULE x) { - FIXME("%p\n", x); + FIXME("(%08x): stub\n", x); return TRUE; } -void *WINAPI I_CryptGetAsn1Decoder(long x) +ASN1decoding_t WINAPI I_CryptGetAsn1Decoder(HCRYPTASN1MODULE x) { - FIXME("%08lx\n", x); + FIXME("(%08x): stub\n", x); + return NULL; +} + +ASN1encoding_t WINAPI I_CryptGetAsn1Encoder(HCRYPTASN1MODULE x) +{ + FIXME("(%08x): stub\n", x); return NULL; } diff --git a/dlls/crypt32/rootstore.c b/dlls/crypt32/rootstore.c index e150c6a087e..7941fa21a69 100644 --- a/dlls/crypt32/rootstore.c +++ b/dlls/crypt32/rootstore.c @@ -30,6 +30,7 @@ #include #endif #include +#include #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" diff --git a/dlls/crypt32/tests/chain.c b/dlls/crypt32/tests/chain.c index e320e79b447..aa84004a3fc 100644 --- a/dlls/crypt32/tests/chain.c +++ b/dlls/crypt32/tests/chain.c @@ -1537,51 +1537,44 @@ static ChainCheck chainCheck[] = { { { sizeof(chain0) / sizeof(chain0[0]), chain0 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_TIME_VALID, 0 }, - 1, simpleStatus0 }, - TODO_INFO }, + 1, simpleStatus0 }, 0 }, { { sizeof(chain1) / sizeof(chain1[0]), chain1 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_SIGNATURE_VALID | CERT_TRUST_IS_NOT_TIME_VALID, 0 }, - 1, simpleStatus1 }, - TODO_INFO }, + 1, simpleStatus1 }, 0 }, { { sizeof(chain2) / sizeof(chain2[0]), chain2 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_TIME_VALID, 0 }, - 1, simpleStatus2 }, - TODO_INFO }, + 1, simpleStatus2 }, 0 }, { { sizeof(chain3) / sizeof(chain3[0]), chain3 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_TIME_VALID, 0 }, - 1, simpleStatus3 }, - TODO_INFO }, + 1, simpleStatus3 }, 0 }, { { sizeof(chain4) / sizeof(chain4[0]), chain4 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_TIME_VALID, 0 }, - 1, simpleStatus4 }, - TODO_INFO }, + 1, simpleStatus4 }, 0 }, { { sizeof(chain5) / sizeof(chain5[0]), chain5 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT | CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT | CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus5 }, - TODO_ERROR | TODO_INFO }, + TODO_ERROR }, { { sizeof(chain6) / sizeof(chain6[0]), chain6 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, - { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus6 }, - TODO_INFO }, + { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus6 }, 0 }, { { sizeof(chain7) / sizeof(chain7[0]), chain7 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, - { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus7 }, - TODO_INFO }, + { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus7 }, 0 }, { { sizeof(chain8) / sizeof(chain8[0]), chain8 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_TIME_VALID, 0 }, 1, simpleStatus8 }, - TODO_ERROR | TODO_INFO }, + TODO_ERROR }, { { sizeof(chain9) / sizeof(chain9[0]), chain9 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT | @@ -1590,29 +1583,24 @@ static ChainCheck chainCheck[] = { TODO_ERROR | TODO_INFO }, { { sizeof(chain10) / sizeof(chain10[0]), chain10 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, - { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus10 }, - TODO_INFO }, + { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus10 }, 0 }, { { sizeof(chain11) / sizeof(chain11[0]), chain11 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, - { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus10 }, - TODO_INFO }, + { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus10 }, 0 }, { { sizeof(chain12) / sizeof(chain12[0]), chain12 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, - { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus12 }, - TODO_INFO }, + { CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus12 }, 0 }, { { sizeof(selfSignedChain) / sizeof(selfSignedChain[0]), selfSignedChain }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_NOT_TIME_VALID | CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, - 1, selfSignedSimpleStatus }, - TODO_INFO }, + 1, selfSignedSimpleStatus }, 0 }, /* The iTunes chain may or may not have its root trusted, so ignore the * error */ { { sizeof(iTunesChain) / sizeof(iTunesChain[0]), iTunesChain }, { { CERT_TRUST_IS_UNTRUSTED_ROOT, CERT_TRUST_HAS_PREFERRED_ISSUER }, { 0, 0 }, - 1, iTunesSimpleStatus }, - TODO_INFO }, + 1, iTunesSimpleStatus }, 0 }, }; static const CERT_TRUST_STATUS elementStatus8NoStore[] = { @@ -1627,7 +1615,7 @@ static ChainCheck chainCheckNoStore[] = { { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_IS_NOT_TIME_VALID | CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, selfSignedSimpleStatus }, - TODO_ERROR | TODO_INFO }, + TODO_ERROR }, { { sizeof(chain8) / sizeof(chain8[0]), chain8 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_UNTRUSTED_ROOT | diff --git a/dlls/d3d9/tests/texture.c b/dlls/d3d9/tests/texture.c index cb7b781d002..36e91430083 100644 --- a/dlls/d3d9/tests/texture.c +++ b/dlls/d3d9/tests/texture.c @@ -126,6 +126,73 @@ static void test_cube_textures(IDirect3DDevice9 *device_ptr, DWORD caps) test_cube_texture_from_pool(device_ptr, caps, D3DPOOL_SCRATCH, FALSE); } +static void test_mipmap_gen(IDirect3DDevice9 *device) +{ + HRESULT hr; + IDirect3D9 *d3d9; + IDirect3DTexture9 *texture; + IDirect3DSurface9 *surface; + DWORD levels; + D3DSURFACE_DESC desc; + int i; + D3DLOCKED_RECT lr; + + hr = IDirect3DDevice9_GetDirect3D(device, &d3d9); + ok(hr == D3D_OK, "IDirect3DDevice9_GetDirect3D returned %#x\n", hr); + + hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, + D3DUSAGE_AUTOGENMIPMAP, + D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8); + if(FAILED(hr)) + { + skip("No mipmap generation support\n"); + } + + hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP, + D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0); + ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed(%08x)\n", hr); + + levels = IDirect3DTexture9_GetLevelCount(texture); + ok(levels == 1, "Got %d levels, expected 1\n", levels); + + for(i = 0; i < 6 /* 64 = 2 ^ 6 */; i++) + { + surface = NULL; + hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface); + ok(hr == (i == 0 ? D3D_OK : D3DERR_INVALIDCALL), + "GetSurfaceLevel on level %d returned %#x\n", i, hr); + if(surface) IDirect3DSurface9_Release(surface); + + hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc); + ok(hr == (i == 0 ? D3D_OK : D3DERR_INVALIDCALL), + "GetLevelDesc on level %d returned %#x\n", i, hr); + + hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0); + ok(hr == (i == 0 ? D3D_OK : D3DERR_INVALIDCALL), + "LockRect on level %d returned %#x\n", i, hr); + if(SUCCEEDED(hr)) + { + hr = IDirect3DTexture9_UnlockRect(texture, i); + ok(hr == D3D_OK, "Unlock returned %08x\n", hr); + } + } + IDirect3DTexture9_Release(texture); + + hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2 /* levels */, D3DUSAGE_AUTOGENMIPMAP, + D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0); + ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateTexture(levels = 2) returned %08x\n", hr); + hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6 /* levels */, D3DUSAGE_AUTOGENMIPMAP, + D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0); + ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateTexture(levels = 6) returned %08x\n", hr); + + hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1 /* levels */, D3DUSAGE_AUTOGENMIPMAP, + D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0); + ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture(levels = 1) returned %08x\n", hr); + levels = IDirect3DTexture9_GetLevelCount(texture); + ok(levels == 1, "Got %d levels, expected 1\n", levels); + IDirect3DTexture9_Release(texture); +} + START_TEST(texture) { D3DCAPS9 caps; @@ -146,4 +213,5 @@ START_TEST(texture) test_texture_stage_states(device_ptr, caps.MaxTextureBlendStages); test_cube_textures(device_ptr, caps.TextureCaps); + test_mipmap_gen(device_ptr); } diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 00506abedb2..2e8fdfed5fc 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -2822,6 +2822,115 @@ static void x8l8v8u8_test(IDirect3DDevice9 *device) IDirect3DTexture9_Release(texture); } +static void autogen_mipmap_test(IDirect3DDevice9 *device) +{ + HRESULT hr; + IDirect3D9 *d3d; + IDirect3DTexture9 *texture = NULL; + IDirect3DSurface9 *surface; + DWORD color; + const RECT r1 = {256, 256, 512, 512}; + const RECT r2 = {512, 256, 768, 512}; + const RECT r3 = {256, 512, 512, 768}; + const RECT r4 = {512, 512, 768, 768}; + unsigned int x, y; + D3DLOCKED_RECT lr; + memset(&lr, 0, sizeof(lr)); + + IDirect3DDevice9_GetDirect3D(device, &d3d); + if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, + D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK) { + skip("No autogenmipmap support\n"); + IDirect3D9_Release(d3d); + return; + } + IDirect3D9_Release(d3d); + + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0); + ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr)); + + /* Make the mipmap big, so that a smaller mipmap is used + */ + hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 0, D3DUSAGE_AUTOGENMIPMAP, + D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0); + ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel returned %s\n", DXGetErrorString9(hr)); + hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0); + ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %s\n", DXGetErrorString9(hr)); + for(y = 0; y < 1024; y++) { + for(x = 0; x < 1024; x++) { + DWORD *dst = (DWORD *) (((BYTE *) lr.pBits) + y * lr.Pitch + x * 4); + POINT pt; + + pt.x = x; + pt.y = y; + if(PtInRect(&r1, pt)) { + *dst = 0xffff0000; + } else if(PtInRect(&r2, pt)) { + *dst = 0xff00ff00; + } else if(PtInRect(&r3, pt)) { + *dst = 0xff0000ff; + } else if(PtInRect(&r4, pt)) { + *dst = 0xff000000; + } else { + *dst = 0xffffffff; + } + } + } + hr = IDirect3DSurface9_UnlockRect(surface); + ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect returned %s\n", DXGetErrorString9(hr)); + IDirect3DSurface9_Release(surface); + + hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture); + ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); + ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_BeginScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr)); + if(SUCCEEDED(hr)) { + const float quad[] = { + -0.5, -0.5, 0.1, 0.0, 0.0, + -0.5, 0.5, 0.1, 0.0, 1.0, + 0.5, -0.5, 0.1, 1.0, 0.0, + 0.5, 0.5, 0.1, 1.0, 1.0 + }; + + hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1); + ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float)); + ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr); + hr = IDirect3DDevice9_EndScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr)); + } + hr = IDirect3DDevice9_SetTexture(device, 0, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); + ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr)); + IDirect3DTexture9_Release(texture); + + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr)); + color = getPixelColor(device, 200, 200); + ok(color == 0x00ffffff, "pixel 200/200 has color %08x, expected 0x00ffffff\n", color); + color = getPixelColor(device, 280, 200); + ok(color == 0x000000ff, "pixel 280/200 has color %08x, expected 0x000000ff\n", color); + color = getPixelColor(device, 360, 200); + ok(color == 0x00000000, "pixel 360/200 has color %08x, expected 0x00000000\n", color); + color = getPixelColor(device, 440, 200); + ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color); + color = getPixelColor(device, 200, 270); + ok(color == 0x00ffffff, "pixel 200/270 has color %08x, expected 0x00ffffff\n", color); + color = getPixelColor(device, 280, 270); + ok(color == 0x00ff0000, "pixel 280/270 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 360, 270); + ok(color == 0x0000ff00, "pixel 360/270 has color %08x, expected 0x0000ff00\n", color); + color = getPixelColor(device, 440, 270); + ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color); +} + START_TEST(visual) { IDirect3DDevice9 *device_ptr; @@ -2899,6 +3008,7 @@ START_TEST(visual) release_buffer_test(device_ptr); float_texture_test(device_ptr); texture_transform_flags_test(device_ptr); + autogen_mipmap_test(device_ptr); if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0)) diff --git a/dlls/dmband/regsvr.c b/dlls/dmband/regsvr.c index 988bb1f6c66..4c4fc0fa2f9 100644 --- a/dlls/dmband/regsvr.c +++ b/dlls/dmband/regsvr.c @@ -101,9 +101,6 @@ static LONG register_key_defvalueA(HKEY base, WCHAR const *name, static LONG register_progid(WCHAR const *clsid, char const *progid, char const *curver_progid, char const *name, char const *extra); -static LONG recursive_delete_key(HKEY key); -static LONG recursive_delete_keyA(HKEY base, char const *name); -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); /*********************************************************************** * register_interfaces @@ -190,7 +187,8 @@ static HRESULT unregister_interfaces(struct regsvr_interface const *list) { WCHAR buf[39]; StringFromGUID2(list->iid, buf, 39); - res = recursive_delete_keyW(interface_key, buf); + res = RegDeleteTreeW(interface_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; } RegCloseKey(interface_key); @@ -295,16 +293,19 @@ static HRESULT unregister_coclasses(struct regsvr_coclass const *list) { WCHAR buf[39]; StringFromGUID2(list->clsid, buf, 39); - res = recursive_delete_keyW(coclass_key, buf); + res = RegDeleteTreeW(coclass_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; if (list->progid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } if (list->viprogid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } } @@ -413,67 +414,6 @@ error_close_progid_key: } /*********************************************************************** - * recursive_delete_key - */ -static LONG recursive_delete_key(HKEY key) { - LONG res; - WCHAR subkey_name[MAX_PATH]; - DWORD cName; - HKEY subkey; - - for (;;) { - cName = sizeof(subkey_name) / sizeof(WCHAR); - res = RegEnumKeyExW(key, 0, subkey_name, &cName, - NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - res = ERROR_SUCCESS; /* presumably we're done enumerating */ - break; - } - res = RegOpenKeyExW(key, subkey_name, 0, - KEY_READ | KEY_WRITE, &subkey); - if (res == ERROR_FILE_NOT_FOUND) continue; - if (res != ERROR_SUCCESS) break; - - res = recursive_delete_key(subkey); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) break; - } - - if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); - return res; -} - -/*********************************************************************** - * recursive_delete_keyA - */ -static LONG recursive_delete_keyA(HKEY base, char const *name) { - LONG res; - HKEY key; - - res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * recursive_delete_keyW - */ -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) { - LONG res; - HKEY key; - - res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** * coclass list */ static struct regsvr_coclass const coclass_list[] = { diff --git a/dlls/dmcompos/regsvr.c b/dlls/dmcompos/regsvr.c index ea3d705a3da..2fcbf8986b2 100644 --- a/dlls/dmcompos/regsvr.c +++ b/dlls/dmcompos/regsvr.c @@ -101,9 +101,6 @@ static LONG register_key_defvalueA(HKEY base, WCHAR const *name, static LONG register_progid(WCHAR const *clsid, char const *progid, char const *curver_progid, char const *name, char const *extra); -static LONG recursive_delete_key(HKEY key); -static LONG recursive_delete_keyA(HKEY base, char const *name); -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); /*********************************************************************** * register_interfaces @@ -190,7 +187,8 @@ static HRESULT unregister_interfaces(struct regsvr_interface const *list) { WCHAR buf[39]; StringFromGUID2(list->iid, buf, 39); - res = recursive_delete_keyW(interface_key, buf); + res = RegDeleteTreeW(interface_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; } RegCloseKey(interface_key); @@ -295,16 +293,19 @@ static HRESULT unregister_coclasses(struct regsvr_coclass const *list) { WCHAR buf[39]; StringFromGUID2(list->clsid, buf, 39); - res = recursive_delete_keyW(coclass_key, buf); + res = RegDeleteTreeW(coclass_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; if (list->progid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } if (list->viprogid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } } @@ -413,67 +414,6 @@ error_close_progid_key: } /*********************************************************************** - * recursive_delete_key - */ -static LONG recursive_delete_key(HKEY key) { - LONG res; - WCHAR subkey_name[MAX_PATH]; - DWORD cName; - HKEY subkey; - - for (;;) { - cName = sizeof(subkey_name) / sizeof(WCHAR); - res = RegEnumKeyExW(key, 0, subkey_name, &cName, - NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - res = ERROR_SUCCESS; /* presumably we're done enumerating */ - break; - } - res = RegOpenKeyExW(key, subkey_name, 0, - KEY_READ | KEY_WRITE, &subkey); - if (res == ERROR_FILE_NOT_FOUND) continue; - if (res != ERROR_SUCCESS) break; - - res = recursive_delete_key(subkey); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) break; - } - - if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); - return res; -} - -/*********************************************************************** - * recursive_delete_keyA - */ -static LONG recursive_delete_keyA(HKEY base, char const *name) { - LONG res; - HKEY key; - - res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * recursive_delete_keyW - */ -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) { - LONG res; - HKEY key; - - res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** * coclass list */ static struct regsvr_coclass const coclass_list[] = { diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 9881f00d6dc..b978d35fa78 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -339,7 +339,7 @@ static const WCHAR defFixed[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0 static const WCHAR RegularW[] = {'R','e','g','u','l','a','r','\0'}; -static const WCHAR fontsW[] = {'\\','F','o','n','t','s','\0'}; +static const WCHAR fontsW[] = {'\\','f','o','n','t','s','\0'}; static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', 'W','i','n','d','o','w','s','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', diff --git a/dlls/kernel32/tests/comm.c b/dlls/kernel32/tests/comm.c index 01ba2b91fa7..66fc770b31c 100644 --- a/dlls/kernel32/tests/comm.c +++ b/dlls/kernel32/tests/comm.c @@ -679,7 +679,17 @@ static HANDLE test_OpenComm(BOOL doOverlap) } if (hcom != INVALID_HANDLE_VALUE) { - ok(ClearCommError(hcom,&errors,&comstat), "Unexpected errors on open\n"); + BOOL ret; + + ret = ClearCommError(hcom, &errors, &comstat); + if (!ret && GetLastError() == ERROR_NOT_READY) + { + trace("%s doesn't respond, skipping the test\n", port_name); + CloseHandle(hcom); + return INVALID_HANDLE_VALUE; + } + + ok(ret, "Unexpected error %u on open\n", GetLastError()); ok(comstat.cbInQue == 0, "Unexpected %d chars in InQueue\n",comstat.cbInQue); ok(comstat.cbOutQue == 0, "Still pending %d charcters in OutQueue\n", comstat.cbOutQue); ok(errors == 0, "Unexpected errors 0x%08x\n", errors); diff --git a/dlls/mshtml/En.rc b/dlls/mshtml/En.rc index cf77ed7bc6d..556a6783f18 100644 --- a/dlls/mshtml/En.rc +++ b/dlls/mshtml/En.rc @@ -39,3 +39,17 @@ FONT 8, "MS Shell Dlg" DEFPUSHBUTTON "&Install", ID_DWL_INSTALL, 200, 60, 50, 15, WS_GROUP | WS_TABSTOP PUSHBUTTON "&Cancel", IDCANCEL, 140, 60, 50, 15, WS_GROUP | WS_TABSTOP } + +IDD_HYPERLINK DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 250, 65 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Hyperlink" +FONT 8, "MS Shell Dlg" +{ + GROUPBOX "Hyperlink Information", IDC_STATIC, 5, 5, 190, 55 + LTEXT "&Type:", IDC_STATIC, 10, 22, 20, 10 + COMBOBOX IDC_TYPE, 35, 20, 45, 100, WS_TABSTOP | WS_GROUP | WS_VSCROLL | CBS_DROPDOWNLIST | CBS_HASSTRINGS + LTEXT "&URL:", IDC_STATIC, 10, 42, 20, 10 + EDITTEXT IDC_URL, 35, 40, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP + PUSHBUTTON "OK", IDOK, 200, 10, 45, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 200, 28, 45, 14, WS_GROUP | WS_TABSTOP +} diff --git a/dlls/mshtml/editor.c b/dlls/mshtml/editor.c index a6270777d01..fa2e75eaf6b 100644 --- a/dlls/mshtml/editor.c +++ b/dlls/mshtml/editor.c @@ -52,6 +52,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); #define NSCMD_FONTFACE "cmd_fontFace" #define NSCMD_INDENT "cmd_indent" #define NSCMD_INSERTHR "cmd_insertHR" +#define NSCMD_INSERTLINKNOUI "cmd_insertLinkNoUI" #define NSCMD_ITALIC "cmd_italic" #define NSCMD_LINENEXT "cmd_lineNext" #define NSCMD_LINEPREVIOUS "cmd_linePrevious" @@ -608,7 +609,7 @@ void handle_edit_event(HTMLDocument *This, nsIDOMEvent *event) void handle_edit_load(HTMLDocument *This) { - This->nscontainer->editor_controller = get_editor_controller(This->nscontainer); + get_editor_controller(This->nscontainer); if(This->ui_active) { OLECHAR wszHTMLDocument[30]; @@ -1120,11 +1121,225 @@ static HRESULT query_edit_status(HTMLDocument *This, OLECMD *cmd) TRACE("CGID_MSHTML: IDM_OUTDENT\n"); cmd->cmdf = query_ns_edit_status(This, NULL); break; + case IDM_HYPERLINK: + TRACE("CGID_MSHTML: IDM_HYPERLINK\n"); + cmd->cmdf = query_ns_edit_status(This, NULL); + break; } return S_OK; } +static INT_PTR CALLBACK hyperlink_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + static const WCHAR wszOther[] = {'(','o','t','h','e','r',')',0}; + + switch (msg) + { + case WM_INITDIALOG: + { + static const WCHAR wszFile[] = {'f','i','l','e',':',0}; + static const WCHAR wszFtp[] = {'f','t','p',':',0}; + static const WCHAR wszHttp[] = {'h','t','t','p',':',0}; + static const WCHAR wszHttps[] = {'h','t','t','p','s',':',0}; + static const WCHAR wszMailto[] = {'m','a','i','l','t','o',':',0}; + static const WCHAR wszNews[] = {'n','e','w','s',':',0}; + INT def_idx; + HWND hwndCB = GetDlgItem(hwnd, IDC_TYPE); + HWND hwndURL = GetDlgItem(hwnd, IDC_URL); + INT len; + + SetWindowLongPtrW(hwnd, DWLP_USER, lparam); + + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszOther); + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszFile); + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszFtp); + def_idx = SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszHttp); + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszHttps); + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszMailto); + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszNews); + SendMessageW(hwndCB, CB_SETCURSEL, def_idx, 0); + + /* force the updating of the URL edit box */ + SendMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_TYPE, CBN_SELCHANGE), (LPARAM)hwndCB); + + SetFocus(hwndURL); + len = SendMessageW(hwndURL, WM_GETTEXTLENGTH, 0, 0); + SendMessageW(hwndURL, EM_SETSEL, 0, len); + + return FALSE; + } + case WM_COMMAND: + switch (wparam) + { + case MAKEWPARAM(IDCANCEL, BN_CLICKED): + EndDialog(hwnd, wparam); + return TRUE; + case MAKEWPARAM(IDOK, BN_CLICKED): + { + BSTR *url = (BSTR *)GetWindowLongPtrW(hwnd, DWLP_USER); + HWND hwndURL = GetDlgItem(hwnd, IDC_URL); + INT len = GetWindowTextLengthW(hwndURL); + *url = SysAllocStringLen(NULL, len + 1); + GetWindowTextW(hwndURL, *url, len + 1); + EndDialog(hwnd, wparam); + return TRUE; + } + case MAKEWPARAM(IDC_TYPE, CBN_SELCHANGE): + { + HWND hwndURL = GetDlgItem(hwnd, IDC_URL); + INT item; + INT len; + LPWSTR type; + LPWSTR url; + LPWSTR p; + static const WCHAR wszSlashSlash[] = {'/','/'}; + + /* get string of currently selected hyperlink type */ + item = SendMessageW((HWND)lparam, CB_GETCURSEL, 0, 0); + len = SendMessageW((HWND)lparam, CB_GETLBTEXTLEN, item, 0); + type = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); + SendMessageW((HWND)lparam, CB_GETLBTEXT, item, (LPARAM)type); + + if (!strcmpW(type, wszOther)) + *type = '\0'; + + /* get current URL */ + len = GetWindowTextLengthW(hwndURL); + url = HeapAlloc(GetProcessHeap(), 0, (len + strlenW(type) + 3) * sizeof(WCHAR)); + GetWindowTextW(hwndURL, url, len + 1); + + /* strip off old protocol */ + p = strchrW(url, ':'); + if (p && p[1] == '/' && p[2] == '/') + p += 3; + if (!p) p = url; + memmove(url + (*type != '\0' ? strlenW(type) + 2 : 0), p, (len + 1 - (p - url)) * sizeof(WCHAR)); + + /* add new protocol */ + if (*type != '\0') + { + memcpy(url, type, strlenW(type) * sizeof(WCHAR)); + memcpy(url + strlenW(type), wszSlashSlash, sizeof(wszSlashSlash)); + } + + SetWindowTextW(hwndURL, url); + + HeapFree(GetProcessHeap(), 0, url); + HeapFree(GetProcessHeap(), 0, type); + return TRUE; + } + } + return FALSE; + case WM_CLOSE: + EndDialog(hwnd, IDCANCEL); + return TRUE; + default: + return FALSE; + } +} + +static HRESULT exec_hyperlink(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out) +{ + BSTR url = NULL; + INT ret; + nsAString ns_url; + PRBool insert_link_at_caret; + nsISelection *nsselection; + + FIXME("%p, 0x%x, %p, %p\n", This, cmdexecopt, in, out); + + if (cmdexecopt == OLECMDEXECOPT_DONTPROMPTUSER) + { + if (!in || V_VT(in) != VT_BSTR) + { + WARN("invalid arg\n"); + return E_INVALIDARG; + } + url = V_BSTR(in); + } + else + { + ret = DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_HYPERLINK), NULL /* FIXME */, hyperlink_dlgproc, (LPARAM)&url); + if (ret != IDOK) + return OLECMDERR_E_CANCELED; + } + + nsselection = get_ns_selection(This); + if (!nsselection) + return E_FAIL; + + nsAString_Init(&ns_url, url); + + nsISelection_GetIsCollapsed(nsselection, &insert_link_at_caret); + + if (insert_link_at_caret) + { + static const WCHAR wszA[] = {'a',0}; + static const WCHAR wszHref[] = {'h','r','e','f',0}; + nsIHTMLEditor *html_editor; + nsIDOMDocument *nsdoc; + nsIDOMNode *text_node; + nsIDOMElement *anchor_elem; + nsIDOMNode *unused_node; + nsAString a_str; + nsAString href_str; + nsresult nsres; + + nsres = nsIWebNavigation_GetDocument(This->nscontainer->navigation, &nsdoc); + if(NS_FAILED(nsres)) + return E_FAIL; + + nsAString_Init(&a_str, wszA); + nsAString_Init(&href_str, wszHref); + + /* create an element for the link */ + nsIDOMDocument_CreateElement(nsdoc, &a_str, &anchor_elem); + nsIDOMElement_SetAttribute(anchor_elem, &href_str, &ns_url); + + nsAString_Finish(&href_str); + nsAString_Finish(&a_str); + + /* create an element with text of URL */ + nsIDOMDocument_CreateTextNode(nsdoc, &ns_url, (nsIDOMText **)&text_node); + + /* wrap the tags around the text element */ + nsIDOMElement_AppendChild(anchor_elem, text_node, &unused_node); + nsIDOMNode_Release(text_node); + nsIDOMNode_Release(unused_node); + + nsIEditor_QueryInterface(This->nscontainer->editor, &IID_nsIHTMLEditor, (void **)&html_editor); + if (html_editor) + { + /* add them to the document at the caret position */ + nsres = nsIHTMLEditor_InsertElementAtSelection(html_editor, anchor_elem, FALSE); + nsIHTMLEditor_Release(html_editor); + } + + nsISelection_SelectAllChildren(nsselection, (nsIDOMNode*)anchor_elem); + + nsIDOMElement_Release(anchor_elem); + nsIDOMDocument_Release(nsdoc); + } + else + { + nsICommandParams *nsparam = create_nscommand_params(); + + nsICommandParams_SetStringValue(nsparam, NSSTATE_ATTRIBUTE, &ns_url); + do_ns_command(This->nscontainer, NSCMD_INSERTLINKNOUI, nsparam); + nsICommandParams_Release(nsparam); + } + + nsAString_Finish(&ns_url); + + nsISelection_Release(nsselection); + + if (cmdexecopt != OLECMDEXECOPT_DONTPROMPTUSER) + SysFreeString(url); + + return S_OK; +} + static HRESULT query_selall_status(HTMLDocument *This, OLECMD *cmd) { TRACE("(%p)->(%p)\n", This, cmd); @@ -1151,6 +1366,7 @@ const cmdtable_t editmode_cmds[] = { {IDM_INDENT, query_edit_status, exec_indent}, {IDM_OUTDENT, query_edit_status, exec_outdent}, {IDM_COMPOSESETTINGS, NULL, exec_composesettings}, + {IDM_HYPERLINK, query_edit_status, exec_hyperlink}, {0,NULL,NULL} }; @@ -1163,3 +1379,15 @@ void init_editor(HTMLDocument *This) set_ns_fontname(This->nscontainer, "Times New Roman"); } + +HRESULT editor_is_dirty(HTMLDocument *This) +{ + PRBool modified; + + if(!This->nscontainer || !This->nscontainer->editor) + return S_FALSE; + + nsIEditor_GetDocumentModified(This->nscontainer->editor, &modified); + + return modified ? S_OK : S_FALSE; +} diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 1f11d7d8960..79935a88d65 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -182,6 +182,7 @@ struct NSContainer { nsIBaseWindow *window; nsIWebBrowserFocus *focus; + nsIEditor *editor; nsIController *editor_controller; LONG ref; @@ -396,7 +397,7 @@ nsICommandParams *create_nscommand_params(void); nsIMutableArray *create_nsarray(void); nsIWritableVariant *create_nsvariant(void); void nsnode_to_nsstring(nsIDOMNode*,nsAString*); -nsIController *get_editor_controller(NSContainer*); +void get_editor_controller(NSContainer*); void init_nsevents(NSContainer*); BSCallback *create_bscallback(IMoniker*); @@ -455,6 +456,7 @@ HRESULT editor_exec_copy(HTMLDocument*,DWORD,VARIANT*,VARIANT*); HRESULT editor_exec_cut(HTMLDocument*,DWORD,VARIANT*,VARIANT*); HRESULT editor_exec_paste(HTMLDocument*,DWORD,VARIANT*,VARIANT*); void handle_edit_load(HTMLDocument *This); +HRESULT editor_is_dirty(HTMLDocument*); extern DWORD mshtml_tls; diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index 0dfdf0ebd27..2a6628b600a 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -629,20 +629,28 @@ void nsnode_to_nsstring(nsIDOMNode *nsdoc, nsAString *str) nsIContentSerializer_Release(serializer); } -nsIController *get_editor_controller(NSContainer *This) +void get_editor_controller(NSContainer *This) { - nsIController *ret = NULL; nsIEditingSession *editing_session = NULL; nsIInterfaceRequestor *iface_req; nsIControllerContext *ctrlctx; - nsIEditor *editor = NULL; nsresult nsres; + if(This->editor) { + nsIEditor_Release(This->editor); + This->editor = NULL; + } + + if(This->editor_controller) { + nsIController_Release(This->editor_controller); + This->editor_controller = NULL; + } + nsres = nsIWebBrowser_QueryInterface(This->webbrowser, &IID_nsIInterfaceRequestor, (void**)&iface_req); if(NS_FAILED(nsres)) { ERR("Could not get nsIInterfaceRequestor: %08x\n", nsres); - return NULL; + return; } nsres = nsIInterfaceRequestor_GetInterface(iface_req, &IID_nsIEditingSession, @@ -650,35 +658,31 @@ nsIController *get_editor_controller(NSContainer *This) nsIInterfaceRequestor_Release(iface_req); if(NS_FAILED(nsres)) { ERR("Could not get nsIEditingSession: %08x\n", nsres); - return NULL; + return; } nsres = nsIEditingSession_GetEditorForWindow(editing_session, - This->doc->window->nswindow, &editor); + This->doc->window->nswindow, &This->editor); nsIEditingSession_Release(editing_session); if(NS_FAILED(nsres)) { ERR("Could not get editor: %08x\n", nsres); - return NULL; + return; } nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_EDITORCONTROLLER_CONTRACTID, NULL, &IID_nsIControllerContext, (void**)&ctrlctx); if(NS_SUCCEEDED(nsres)) { - nsres = nsIControllerContext_SetCommandContext(ctrlctx, editor); + nsres = nsIControllerContext_SetCommandContext(ctrlctx, (nsISupports *)This->editor); if(NS_FAILED(nsres)) ERR("SetCommandContext failed: %08x\n", nsres); nsres = nsIControllerContext_QueryInterface(ctrlctx, &IID_nsIController, - (void**)&ret); + (void**)&This->editor_controller); nsIControllerContext_Release(ctrlctx); if(NS_FAILED(nsres)) ERR("Could not get nsIController interface: %08x\n", nsres); }else { ERR("Could not create edit controller: %08x\n", nsres); } - - nsISupports_Release(editor); - - return ret; } void set_ns_editmode(NSContainer *This) @@ -1513,6 +1517,7 @@ NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent) ret->bscallback = NULL; ret->content_listener = NULL; ret->editor_controller = NULL; + ret->editor = NULL; if(parent) nsIWebBrowserChrome_AddRef(NSWBCHROME(parent)); @@ -1627,6 +1632,11 @@ void NSContainer_Release(NSContainer *This) This->editor_controller = NULL; } + if(This->editor) { + nsIEditor_Release(This->editor); + This->editor = NULL; + } + if(This->content_listener) { nsIURIContentListener_Release(This->content_listener); This->content_listener = NULL; diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 120c2f6ce52..4a3347d0f24 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -72,6 +72,15 @@ interface nsILoadGroup; interface nsIDOMNode; interface nsIDOMDocument; interface nsIDOMEvent; +interface nsIEditor; +interface nsISelectionController; +interface nsITransactionManager; +interface nsITransaction; +interface nsIInlineSpellChecker; +interface nsIOutputStream; +interface nsIEditorObserver; +interface nsIEditActionListener; +interface nsIDocumentStateListener; interface IMoniker; @@ -105,7 +114,6 @@ typedef nsISupports nsIDOMEntityReference; typedef nsISupports nsIDOMHTMLFormElement; typedef nsISupports nsIDOMHTMLOptionsCollection; typedef nsISupports nsIDOMHTMLCollection; -typedef nsISupports nsIEditor; typedef nsISupports nsIWebProgressListener; typedef nsISupports nsIDOMCSSValue; typedef nsISupports nsIDOMCSSRule; @@ -113,6 +121,8 @@ typedef nsISupports nsIPrintSession; typedef nsISupports nsIControllerCommandTable; typedef nsISupports nsIPrincipal; typedef nsISupports nsIAtom; +typedef nsISupports nsISupportsArray; +typedef nsISupports nsIContentFilter; [ object, @@ -1884,6 +1894,154 @@ interface nsIScriptContainer : nsISupports nsresult DropScriptObject(void *aObject); } +[ + object, + uuid(D4882FFB-E927-408b-96BE-D4391B456FA9) +] +interface nsIEditor : nsISupports +{ + typedef void *nsIPresShellPtr; + typedef void *nsIContentPtr; + + nsresult GetSelection([out] nsISelection *_retval); + nsresult Init([in] nsIDOMDocument *doc, [in] nsIPresShellPtr shell, [in] nsIContentPtr aRoot, [in] nsISelectionController *aSelCon, [in] PRUint32 aFlags); + nsresult SetAttributeOrEquivalent([in] nsIDOMElement *element, [in] const nsAString *sourceAttrName, [in] const nsAString *sourceAttrValue, [in] PRBool aSuppressTransaction); + nsresult RemoveAttributeOrEquivalent([in] nsIDOMElement *element, [in] const nsAString *sourceAttrName, [in] PRBool aSuppressTransaction); + nsresult PostCreate(); + nsresult PreDestroy(); + nsresult GetFlags([out] PRUint32 *_retval); + nsresult SetFlags([in] PRUint32 val); + nsresult GetContentsMIMEType([out] char **_retval); + nsresult SetContentsMIMEType([in] const char *val); + nsresult GetIsDocumentEditable([out] PRBool *_retval); + nsresult GetDocument([out] nsIDOMDocument **_retval); + nsresult GetRootElement([out] nsIDOMElement **_retval); + nsresult GetSelectionController([out] nsISelectionController **_retval); + nsresult DeleteSelection([in] PRInt16 action); + nsresult GetDocumentIsEmpty([out] PRBool *_retval); + nsresult GetDocumentModified([out] PRBool *_retval); + nsresult GetDocumentCharacterSet([out] nsACString *_retval); + nsresult SetDocumentCharacterSet([in] const nsACString *val); + nsresult ResetModificationCount(); + nsresult GetModificationCount([out] PRInt32 *_retval); + nsresult IncrementModificationCount([in] long aModCount); + nsresult GetTransactionManager([out] nsITransactionManager **_retval); + nsresult DoTransaction([in] nsITransaction *txn); + nsresult EnableUndo([in] PRBool enable); + nsresult Undo([in] PRUint32 count); + nsresult CanUndo([out] PRBool *isEnabled, [out] PRBool *canUndo); + nsresult Redo([in] PRUint32 count); + nsresult CanRedo([out] PRBool *isEnabled, [out] PRBool *canRedo); + nsresult BeginTransaction(); + nsresult EndTransaction(); + nsresult BeginPlaceHolderTransaction([in] nsIAtom *name); + nsresult EndPlaceHolderTransaction(); + nsresult ShouldTxnSetSelection([out] PRBool *_retval); + nsresult SetShouldTxnSetSelection([in] PRBool should); + nsresult GetInlineSpellChecker([out] nsIInlineSpellChecker **_retval); + nsresult Cut(); + nsresult CanCut([out] PRBool *_retval); + nsresult Copy(); + nsresult CanCopy([out] PRBool *_retval); + nsresult Paste([in] PRInt32 aSelectionType); + nsresult CanPaste([in] PRInt32 aSelectionType, [out] PRBool *_retval); + nsresult SelectAll(); + nsresult BeginningOfDocument(); + nsresult EndOfDocument(); + nsresult CanDrag([in] nsIDOMEvent *aEvent, [out] PRBool *_retval); + nsresult DoDrag([in] nsIDOMEvent *aEvent); + nsresult InsertFromDrop([in] nsIDOMEvent *aEvent); + nsresult SetAttribute([in] nsIDOMElement *aElement, [in] const nsAString *attributestr, [in] const nsAString *attvalue); + nsresult GetAttributeValue([in] nsIDOMElement *aElement, [in] const nsAString *attributestr, [out] nsAString *resultValue, PRBool *_retval); + nsresult RemoveAttribute([in] nsIDOMElement *aElement, [in] const nsAString *aAttribute); + nsresult CloneAttribute([in] const nsAString *aAttribute, [in] nsIDOMNode *aDestNode, [in] nsIDOMNode *aSourceNode); + nsresult CloneAttributes([in] nsIDOMNode *destNode, [in] nsIDOMNode *sourceNode); + nsresult CreateNode([in] const nsAString *tag, [in] nsIDOMNode parent, [in] PRInt32 position, [out] nsIDOMNode **_retval); + nsresult InsertNode([in] nsIDOMNode *node, [in] nsIDOMNode *parent, [in] PRInt32 aPosition); + nsresult SplitNode([in] nsIDOMNode *existingRightNode, [in] PRInt32 offset, [out] nsIDOMNode **newLeftNode); + nsresult JoinNodes([in] nsIDOMNode *leftNode, [in] nsIDOMNode *rightNode, [in] nsIDOMNode *parent); + nsresult DeleteNode([in] nsIDOMNode *child); + nsresult MarkNodeDirty([in] nsIDOMNode *node); + nsresult SwitchTextDirection(); + nsresult OutputToString([in] nsAString formatType, [in] PRUint32 flags, [out] nsAString *_retval); + nsresult OutputToStream([in] nsIOutputStream *aStream, [in] nsAString *formatType, [in] nsACString *charsetOverride, [in] PRUint32 flags); + nsresult AddEditorObserver([in] nsIEditorObserver *observer); + nsresult RemoveEditorObserver([in] nsIEditorObserver *observer); + nsresult AddEditActionListener([in] nsIEditActionListener *listener); + nsresult RemoveEditActionListener([in] nsIEditActionListener *listener); + nsresult AddDocumentStateListener([in] nsIDocumentStateListener *listener); + nsresult RemoveDocumentStateListener([in] nsIDocumentStateListener *listener); + nsresult DumpContentTree(); + nsresult DebugDumpContent(); + nsresult DebugUnitTests([out] PRInt32 *outNumTests, [out] PRInt32 *outNumTestsFailed); +} + +[ + object, + uuid(afc36593-5787-4420-93d9-b2c0ccbf0cad) +] +interface nsIHTMLEditor : nsISupports +{ + nsresult AddDefaultProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue); + nsresult RemoveDefaultProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue); + nsresult RemoveAllDefaultProperties(); + nsresult SetCSSInlineProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue); + nsresult SetInlineProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue); + nsresult GetInlineProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue, [out] PRBool *aFirst, [out] PRBool *aAny, [out] PRBool *aAll); + nsresult GetInlinePropertyWithAttrValue([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue, [out] PRBool *aFirst, [out] PRBool *aAny, [out] PRBool *aAll, [out] nsAString *_retval); + nsresult RemoveAllInlineProperties(); + nsresult RemoveInlineProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute); + nsresult IncreaseFontSize(); + nsresult DecreaseFontSize(); + nsresult CanDrag([in] nsIDOMEvent *aEvent, [out] PRBool *_retval); + nsresult DoDrag([in] nsIDOMEvent *aEvent); + nsresult InsertFromDrop([in] nsIDOMEvent *aEvent); + nsresult NodeIsBlock([in] nsIDOMNode *node, PRBool *_retval); + nsresult InsertHTML([in] nsAString *aInputString); + nsresult PasteNoFormatting([in] PRInt32 aSelectionType); + nsresult RebuildDocumentFromSource([in] nsAString *aSourceString); + nsresult InsertHTMLWithContext([in] nsAString *aInputString, [in] nsAString *aContextStr, [in] nsAString *aInfoStr, [in] nsAString *aFlavor, [in] nsIDOMDocument *aSourceDoc, [in] nsIDOMNode *aDestinationNode, [in] PRInt32 aDestinationOffset, [in] PRBool aDeleteSelection); + nsresult InsertElementAtSelection([in] nsIDOMElement *aElement, [in] PRBool aDeleteSelection); + nsresult SetDocumentTitle([in] nsAString *aTitle); + nsresult UpdateBaseURL(); + nsresult SelectElement([in] nsIDOMElement *aElement); + nsresult SetCaretAfterElement([in] nsIDOMElement *aElement); + nsresult SetParagraphFormat([in] nsAString *aParagraphFormat); + nsresult GetParagraphState([out] PRBool *aMixed, [out] nsAString *_retval); + nsresult GetFontFaceState([out] PRBool *aMixed, [out] nsAString *_retval); + nsresult GetFontColorState([out] PRBool *aMixed, [out] nsAString *_retval); + nsresult GetBackgroundColorState([out] PRBool *aMixed, [out] nsAString *_retval); + nsresult GetHighlightColorState([out] PRBool *aMixed, [out] nsAString *_retval); + nsresult GetListState([out] PRBool *aMixed, [out] PRBool *aOL, [out] PRBool *aUL, [out] PRBool *aDL); + nsresult GetListItemState([out] PRBool *aMixed, [out] PRBool *aLI, [out] PRBool *aDT, [out] PRBool *aDD); + nsresult GetAlignment([out] PRBool *aMixed, [out] PRInt16 *aAlign); + nsresult GetIndentState([out] PRBool *aCanIndent, [out] PRBool *aCanOutdent); + nsresult MakeOrChangeList([in] nsAString *aListType, [in] PRBool entireList, [in] nsAString *aBulletType); + nsresult RemoveList([in] nsAString *aListType); + nsresult Indent([in] nsAString *aIndent); + nsresult Align([in] nsAString *aAlign); + nsresult GetElementOrParentByTagName([in] nsAString *aTagName, [in] nsIDOMNode *aNode, [out] nsIDOMElement **_retval); + nsresult GetSelectedElement([in] nsAString *aTagName, [out] nsIDOMElement **_retval); + nsresult GetHeadContentsAsHTML([out] nsAString *_retval); + nsresult ReplaceHeadContentsWithHTML([in] nsAString *aSourceToInsert); + nsresult CreateElementWithDefaults([in] nsAString *aTagName, [out] nsIDOMElement **_retval); + nsresult InsertLinkAroundSelection([in] nsIDOMElement *aAnchorElement); + nsresult SetBackgroundColor([in] nsAString *aColor); + nsresult SetBodyAttribute([in] nsAString *aAttr, [in] nsAString *aValue); + nsresult IgnoreSpuriousDragEvent([in] PRBool aIgnoreSpuriousDragEvent); + nsresult GetLinkedObjects([out] nsISupportsArray **_retval); + nsresult GetIsCSSEnabled([out] PRBool *_retval); + nsresult SetIsCSSEnabled([in] PRBool prb); + nsresult AddInsertionListener([in] nsIContentFilter *inFilter); + nsresult RemoveInsertionListener([in] nsIContentFilter *inFilter); + nsresult CreateAnonymousElement([in] nsAString *aTag, [in] nsIDOMNode *aParentNode, [in] nsAString *aAnonClass, [in] PRBool aIsCreatedHidden, [out] nsIDOMElement **_retval); + nsresult GetSelectionContainer([out] nsIDOMElement **_retval); + nsresult CheckSelectionStateForAnonymousButtons([in] nsISelection *aSelection); + nsresult IsAnonymousElement([in] nsIDOMElement *aElement, [out] PRBool *_retval); + nsresult GetReturnInParagraphCreatesNewParagraph([out] PRBool *_retval); + nsresult SetReturnInParagraphCreatesNewParagraph([in] PRBool prb); +} + /* * NOTE: * This is a private Wine interface that is implemented by our implementation diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c index 3b606d6cc53..9f74c91d05c 100644 --- a/dlls/mshtml/persist.c +++ b/dlls/mshtml/persist.c @@ -600,7 +600,7 @@ static HRESULT WINAPI PersistStreamInit_IsDirty(IPersistStreamInit *iface) TRACE("(%p)\n", This); if(This->usermode == EDITMODE) - FIXME("Unimplemented in edit mode\n"); + return editor_is_dirty(This); return S_FALSE; } diff --git a/dlls/mshtml/resource.h b/dlls/mshtml/resource.h index 27dae83502d..f8415f3c52d 100644 --- a/dlls/mshtml/resource.h +++ b/dlls/mshtml/resource.h @@ -49,3 +49,9 @@ #define IDM_DUMPLAYOUTRECTS 6017 #define _IDM_REFRESH 6042 + +#define IDD_HYPERLINK 8000 + +#define IDC_STATIC 9000 +#define IDC_URL 9001 +#define IDC_TYPE 9002 diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 662b42a8dba..b4022e7945b 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -181,14 +181,17 @@ struct apartment_loaded_dll { struct list entry; OpenDll *dll; + DWORD unload_time; + BOOL multi_threaded; }; static const WCHAR wszAptWinClass[] = {'O','l','e','M','a','i','n','T','h','r','e','a','d','W','n','d','C','l','a','s','s',' ', '0','x','#','#','#','#','#','#','#','#',' ',0}; static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, + BOOL apartment_threaded, REFCLSID rclsid, REFIID riid, void **ppv); -static void apartment_freeunusedlibraries(struct apartment *apt); +static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay); static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret); static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name); @@ -403,7 +406,7 @@ DWORD apartment_release(struct apartment *apt) if (apt->filter) IUnknown_Release(apt->filter); /* free as many unused libraries as possible... */ - apartment_freeunusedlibraries(apt); + apartment_freeunusedlibraries(apt, 0); /* ... and free the memory for the apartment loaded dll entry and * release the dll list reference without freeing the library for the @@ -500,6 +503,7 @@ struct host_object_params HANDLE event; /* event signalling when ready for multi-threaded case */ HRESULT hr; /* result for multi-threaded case */ IStream *stream; /* stream that the object will be marshaled into */ + BOOL apartment_threaded; /* is the component purely apartment-threaded? */ }; static HRESULT apartment_hostobject(struct apartment *apt, @@ -519,7 +523,8 @@ static HRESULT apartment_hostobject(struct apartment *apt, return REGDB_E_CLASSNOTREG; } - hr = apartment_getclassobject(apt, dllpath, ¶ms->clsid, ¶ms->iid, (void **)&object); + hr = apartment_getclassobject(apt, dllpath, params->apartment_threaded, + ¶ms->clsid, ¶ms->iid, (void **)&object); if (FAILED(hr)) return hr; @@ -677,6 +682,7 @@ static HRESULT apartment_hostobject_in_hostapt(struct apartment *apt, BOOL multi hr = CreateStreamOnHGlobal(NULL, TRUE, ¶ms.stream); if (FAILED(hr)) return hr; + params.apartment_threaded = !multi_threaded; if (multi_threaded) { params.hr = S_OK; @@ -742,6 +748,7 @@ void apartment_joinmta(void) } static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, + BOOL apartment_threaded, REFCLSID rclsid, REFIID riid, void **ppv) { static const WCHAR wszOle32[] = {'o','l','e','3','2','.','d','l','l',0}; @@ -779,6 +786,8 @@ static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, hr = E_OUTOFMEMORY; if (SUCCEEDED(hr)) { + apartment_loaded_dll->unload_time = 0; + apartment_loaded_dll->multi_threaded = FALSE; hr = COMPOBJ_DllList_Add( dllpath, &apartment_loaded_dll->dll ); if (FAILED(hr)) HeapFree(GetProcessHeap(), 0, apartment_loaded_dll); @@ -794,6 +803,11 @@ static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, if (SUCCEEDED(hr)) { + /* one component being multi-threaded overrides any number of + * apartment-threaded components */ + if (!apartment_threaded) + apartment_loaded_dll->multi_threaded = TRUE; + TRACE("calling DllGetClassObject %p\n", apartment_loaded_dll->dll->DllGetClassObject); /* OK: get the ClassObject */ hr = apartment_loaded_dll->dll->DllGetClassObject(rclsid, riid, ppv); @@ -805,7 +819,7 @@ static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, return hr; } -static void apartment_freeunusedlibraries(struct apartment *apt) +static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay) { struct apartment_loaded_dll *entry, *next; EnterCriticalSection(&apt->cs); @@ -813,10 +827,27 @@ static void apartment_freeunusedlibraries(struct apartment *apt) { if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK)) { - list_remove(&entry->entry); - COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE); - HeapFree(GetProcessHeap(), 0, entry); + DWORD real_delay = delay; + + if (real_delay == INFINITE) + { + if (entry->multi_threaded) + real_delay = 10 * 60 * 1000; /* 10 minutes */ + else + real_delay = 0; + } + + if (!real_delay || (entry->unload_time && (entry->unload_time < GetTickCount()))) + { + list_remove(&entry->entry); + COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE); + HeapFree(GetProcessHeap(), 0, entry); + } + else + entry->unload_time = GetTickCount() + real_delay; } + else if (entry->unload_time) + entry->unload_time = 0; } LeaveCriticalSection(&apt->cs); } @@ -2076,7 +2107,9 @@ static HRESULT get_inproc_class_object(APARTMENT *apt, HKEY hkeydll, return REGDB_E_CLASSNOTREG; } - return apartment_getclassobject(apt, dllpath, rclsid, riid, ppv); + return apartment_getclassobject(apt, dllpath, + !strcmpiW(threading_model, wszApartment), + rclsid, riid, ppv); } /*********************************************************************** @@ -2482,13 +2515,16 @@ void WINAPI CoFreeAllLibraries(void) /* NOP */ } - /*********************************************************************** - * CoFreeUnusedLibraries [OLE32.@] - * CoFreeUnusedLibraries [COMPOBJ.17] + * CoFreeUnusedLibrariesEx [OLE32.@] * - * Frees any unused libraries. Unused are identified as those that return - * S_OK from their DllCanUnloadNow function. + * Frees any previously unused libraries whose delay has expired and marks + * currently unused libraries for unloading. Unused are identified as those that + * return S_OK from their DllCanUnloadNow function. + * + * PARAMS + * dwUnloadDelay [I] Unload delay in milliseconds. + * dwReserved [I] Reserved. Set to 0. * * RETURNS * Nothing. @@ -2496,7 +2532,7 @@ void WINAPI CoFreeAllLibraries(void) * SEE ALSO * CoLoadLibrary, CoFreeAllLibraries, CoFreeLibrary */ -void WINAPI CoFreeUnusedLibraries(void) +void WINAPI CoFreeUnusedLibrariesEx(DWORD dwUnloadDelay, DWORD dwReserved) { struct apartment *apt = COM_CurrentApt(); if (!apt) @@ -2505,7 +2541,25 @@ void WINAPI CoFreeUnusedLibraries(void) return; } - apartment_freeunusedlibraries(apt); + apartment_freeunusedlibraries(apt, dwUnloadDelay); +} + +/*********************************************************************** + * CoFreeUnusedLibraries [OLE32.@] + * CoFreeUnusedLibraries [COMPOBJ.17] + * + * Frees any unused libraries. Unused are identified as those that return + * S_OK from their DllCanUnloadNow function. + * + * RETURNS + * Nothing. + * + * SEE ALSO + * CoLoadLibrary, CoFreeAllLibraries, CoFreeLibrary + */ +void WINAPI CoFreeUnusedLibraries(void) +{ + CoFreeUnusedLibrariesEx(INFINITE, 0); } /*********************************************************************** diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index e018b0fbe50..0b6299554d9 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -20,6 +20,7 @@ @ stdcall CoFreeAllLibraries() @ stdcall CoFreeLibrary(long) @ stdcall CoFreeUnusedLibraries() +@ stdcall CoFreeUnusedLibrariesEx(long long) @ stdcall CoGetCallContext(ptr ptr) @ stub CoGetCallerTID @ stdcall CoGetClassObject(ptr long ptr ptr ptr) diff --git a/dlls/rpcrt4/rpc_message.c b/dlls/rpcrt4/rpc_message.c index 37839f7ce87..ce8d1e7ac9f 100644 --- a/dlls/rpcrt4/rpc_message.c +++ b/dlls/rpcrt4/rpc_message.c @@ -415,7 +415,7 @@ static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection, sec_status = DecryptMessage(&Connection->ctx, &message, 0 /* FIXME */, 0); if (sec_status != SEC_E_OK) { - ERR("EncryptMessage failed with 0x%08x\n", sec_status); + ERR("DecryptMessage failed with 0x%08x\n", sec_status); return RPC_S_SEC_PKG_ERROR; } } @@ -828,12 +828,15 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, if ((common_hdr.ptype != PKT_BIND) && (common_hdr.ptype != PKT_BIND_ACK) && (common_hdr.ptype != PKT_AUTH3)) + { status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_RECEIVE, *Header, hdr_length, (unsigned char *)pMsg->Buffer + buffer_length, data_length, (RpcAuthVerifier *)auth_data, (unsigned char *)auth_data + sizeof(RpcAuthVerifier), header_auth_len - sizeof(RpcAuthVerifier)); + if (status != RPC_S_OK) goto fail; + } } buffer_length += data_length; diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c index 4002f27fa19..3318da65119 100644 --- a/dlls/rsaenh/rsaenh.c +++ b/dlls/rsaenh/rsaenh.c @@ -2080,7 +2080,16 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, } memcpy(in, out, pCryptKey->dwBlockLen); } - if (Final) *pdwDataLen -= pbData[*pdwDataLen-1]; + if (Final) { + if (pbData[*pdwDataLen-1] && + pbData[*pdwDataLen-1] <= pCryptKey->dwBlockLen && + pbData[*pdwDataLen-1] < *pdwDataLen) + *pdwDataLen -= pbData[*pdwDataLen-1]; + else { + SetLastError(NTE_BAD_DATA); + return FALSE; + } + } } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) { encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen); diff --git a/dlls/setupapi/stringtable.c b/dlls/setupapi/stringtable.c index 7be6b1880f2..985e7779501 100644 --- a/dlls/setupapi/stringtable.c +++ b/dlls/setupapi/stringtable.c @@ -86,7 +86,7 @@ StringTableInitialize(VOID) pStringTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE); if (pStringTable->pSlots == NULL) { - MyFree(pStringTable->pSlots); + MyFree(pStringTable); return NULL; } @@ -131,7 +131,7 @@ StringTableInitializeEx(DWORD dwMaxExtraDataSize, pStringTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE); if (pStringTable->pSlots == NULL) { - MyFree(pStringTable->pSlots); + MyFree(pStringTable); return NULL; } diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c index ef249273c49..bf15e055722 100644 --- a/dlls/shell32/pidl.c +++ b/dlls/shell32/pidl.c @@ -2304,7 +2304,7 @@ void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl) * * copies an aPidl struct */ -LPITEMIDLIST* _ILCopyaPidl(LPCITEMIDLIST * apidlsrc, UINT cidl) +LPITEMIDLIST* _ILCopyaPidl(const LPCITEMIDLIST * apidlsrc, UINT cidl) { UINT i; LPITEMIDLIST *apidldest; @@ -2324,7 +2324,7 @@ LPITEMIDLIST* _ILCopyaPidl(LPCITEMIDLIST * apidlsrc, UINT cidl) * * creates aPidl from CIDA */ -LPITEMIDLIST* _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida) +LPITEMIDLIST* _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, const CIDA * cida) { UINT i; LPITEMIDLIST *dst; @@ -2334,10 +2334,10 @@ LPITEMIDLIST* _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida) return NULL; if (pidl) - *pidl = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[0]])); + *pidl = ILClone((LPCITEMIDLIST)(&((const BYTE*)cida)[cida->aoffset[0]])); for (i = 0; i < cida->cidl; i++) - dst[i] = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[i + 1]])); + dst[i] = ILClone((LPCITEMIDLIST)(&((const BYTE*)cida)[cida->aoffset[i + 1]])); return dst; } diff --git a/dlls/shell32/pidl.h b/dlls/shell32/pidl.h index 06372fa7820..010947c19cb 100644 --- a/dlls/shell32/pidl.h +++ b/dlls/shell32/pidl.h @@ -275,8 +275,8 @@ BOOL pcheck (LPCITEMIDLIST pidl); * aPidl helper */ void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl); -LPITEMIDLIST * _ILCopyaPidl(LPCITEMIDLIST * apidlsrc, UINT cidl); -LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida); +LPITEMIDLIST * _ILCopyaPidl(const LPCITEMIDLIST * apidlsrc, UINT cidl); +LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, const CIDA * cida); BOOL WINAPI ILGetDisplayNameExA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPSTR path, DWORD type); BOOL WINAPI ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type); diff --git a/dlls/shell32/shell.c b/dlls/shell32/shell.c index 2703c7ae04a..26b614636c7 100644 --- a/dlls/shell32/shell.c +++ b/dlls/shell32/shell.c @@ -307,7 +307,7 @@ static LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry) /**********************************************************************/ -SEGPTR WINAPI FindEnvironmentString16(LPSTR str) +SEGPTR WINAPI FindEnvironmentString16(LPCSTR str) { SEGPTR spEnv; LPSTR lpEnv,lpString; TRACE("\n"); diff --git a/dlls/shell32/shlfolder.c b/dlls/shell32/shlfolder.c index cbbd12fae60..b6bdd076d9c 100644 --- a/dlls/shell32/shlfolder.c +++ b/dlls/shell32/shlfolder.c @@ -50,28 +50,6 @@ WINE_DEFAULT_DEBUG_CHANNEL (shell); -static CRITICAL_SECTION SHELL32_SF_ClassCacheCS; -static CRITICAL_SECTION_DEBUG critsect_debug = -{ - 0, 0, &SHELL32_SF_ClassCacheCS, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": SHELL32_SF_ClassCacheCS") } -}; -static CRITICAL_SECTION SHELL32_SF_ClassCacheCS = { &critsect_debug, -1, 0, 0, 0, 0 }; - -/* IShellFolder class cache */ -struct _sf_cls_cache_entry -{ - CLSID clsid; - LPVOID pv; -}; - -static struct _sf_class_cache -{ - DWORD allocated, used; - struct _sf_cls_cache_entry *sf_cls_cache_entry; -} sf_cls_cache; - static const WCHAR wszDotShellClassInfo[] = { '.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0}; @@ -204,70 +182,6 @@ HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, return hr; } -static BOOL get_iface_from_cache(REFCLSID clsid, LPVOID *ppvOut) -{ - BOOL ret = FALSE; - int i; - - EnterCriticalSection(&SHELL32_SF_ClassCacheCS); - - for (i = 0; i < sf_cls_cache.used; i++) - { - if (IsEqualIID(&sf_cls_cache.sf_cls_cache_entry[i].clsid, clsid)) - { - *ppvOut = sf_cls_cache.sf_cls_cache_entry[i].pv; - /* Pin it */ - IUnknown_AddRef((IUnknown *)*ppvOut); - ret = TRUE; - break; - } - } - - LeaveCriticalSection(&SHELL32_SF_ClassCacheCS); - return ret; -} - -static void add_iface_to_cache(REFCLSID clsid, LPVOID pv) -{ - EnterCriticalSection(&SHELL32_SF_ClassCacheCS); - - if (sf_cls_cache.used >= sf_cls_cache.allocated) - { - DWORD allocated; - struct _sf_cls_cache_entry *sf_cls_cache_entry; - - if (!sf_cls_cache.allocated) - { - allocated = 4; - sf_cls_cache_entry = HeapAlloc(GetProcessHeap(), 0, - 4 * sizeof(*sf_cls_cache_entry)); - } - else - { - allocated = sf_cls_cache.allocated * 2; - sf_cls_cache_entry = HeapReAlloc(GetProcessHeap(), 0, sf_cls_cache.sf_cls_cache_entry, - allocated * sizeof(*sf_cls_cache_entry)); - } - if (!sf_cls_cache_entry) - { - LeaveCriticalSection(&SHELL32_SF_ClassCacheCS); - return; - } - - sf_cls_cache.allocated = allocated; - sf_cls_cache.sf_cls_cache_entry = sf_cls_cache_entry; - } - - /* Pin it */ - IUnknown_AddRef((IUnknown *)pv); - - sf_cls_cache.sf_cls_cache_entry[sf_cls_cache.used].clsid = *clsid; - sf_cls_cache.sf_cls_cache_entry[sf_cls_cache.used].pv = pv; - sf_cls_cache.used++; - - LeaveCriticalSection(&SHELL32_SF_ClassCacheCS); -} - /*********************************************************************** * SHELL32_CoCreateInitSF * @@ -281,22 +195,11 @@ static void add_iface_to_cache(REFCLSID clsid, LPVOID pv) static HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, LPCITEMIDLIST pidlChild, REFCLSID clsid, LPVOID * ppvOut) { - HRESULT hr = S_OK; + HRESULT hr; TRACE ("%p %s %p\n", pidlRoot, debugstr_w(pathRoot), pidlChild); - if (!get_iface_from_cache(clsid, ppvOut)) - { - hr = SHCoCreateInstance(NULL, clsid, NULL, &IID_IShellFolder, ppvOut); - if (SUCCEEDED(hr)) - { - TRACE("loaded %p %s\n", *ppvOut, wine_dbgstr_guid(clsid)); - add_iface_to_cache(clsid, *ppvOut); - } - } - else - TRACE("found in the cache %p %s\n", *ppvOut, wine_dbgstr_guid(clsid)); - + hr = SHCoCreateInstance(NULL, clsid, NULL, &IID_IShellFolder, ppvOut); if (SUCCEEDED (hr)) { LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild); diff --git a/dlls/winealsa.drv/dscapture.c b/dlls/winealsa.drv/dscapture.c index 7c1aaad1bb2..8c2d9f5c778 100644 --- a/dlls/winealsa.drv/dscapture.c +++ b/dlls/winealsa.drv/dscapture.c @@ -56,27 +56,38 @@ #ifdef HAVE_ALSA +/* Notify timer checks every 10 ms with a resolution of 2 ms */ +#define DS_TIME_DEL 10 +#define DS_TIME_RES 2 + WINE_DEFAULT_DEBUG_CHANNEL(dsalsa); -typedef struct IDsCaptureDriverImpl IDsCaptureDriverImpl; typedef struct IDsCaptureDriverBufferImpl IDsCaptureDriverBufferImpl; -struct IDsCaptureDriverImpl +typedef struct IDsCaptureDriverImpl { - /* IUnknown fields */ const IDsCaptureDriverVtbl *lpVtbl; LONG ref; - - /* IDsCaptureDriverImpl fields */ IDsCaptureDriverBufferImpl* capture_buffer; UINT wDevID; -}; +} IDsCaptureDriverImpl; + +typedef struct IDsCaptureDriverNotifyImpl +{ + const IDsDriverNotifyVtbl *lpVtbl; + LONG ref; + IDsCaptureDriverBufferImpl *buffer; + DSBPOSITIONNOTIFY *notifies; + DWORD nrofnotifies, playpos; + UINT timerID; +} IDsCaptureDriverNotifyImpl; struct IDsCaptureDriverBufferImpl { const IDsCaptureDriverBufferVtbl *lpVtbl; LONG ref; - IDsCaptureDriverImpl* drv; + IDsCaptureDriverImpl *drv; + IDsCaptureDriverNotifyImpl *notify; CRITICAL_SECTION pcm_crst; LPBYTE mmap_buffer, presented_buffer; @@ -91,6 +102,167 @@ struct IDsCaptureDriverBufferImpl snd_pcm_uframes_t mmap_buflen_frames, mmap_pos; }; +static void Capture_CheckNotify(IDsCaptureDriverNotifyImpl *This, DWORD from, DWORD len) +{ + unsigned i; + for (i = 0; i < This->nrofnotifies; ++i) { + LPDSBPOSITIONNOTIFY event = This->notifies + i; + DWORD offset = event->dwOffset; + TRACE("checking %d, position %d, event = %p\n", i, offset, event->hEventNotify); + + if (offset == DSBPN_OFFSETSTOP) { + if (!from && !len) { + SetEvent(event->hEventNotify); + TRACE("signalled event %p (%d)\n", event->hEventNotify, i); + return; + } + else return; + } + + if (offset >= from && offset < (from + len)) + { + TRACE("signalled event %p (%d)\n", event->hEventNotify, i); + SetEvent(event->hEventNotify); + } + } +} + +static void CALLBACK Capture_Notify(UINT timerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) +{ + IDsCaptureDriverBufferImpl *This = (IDsCaptureDriverBufferImpl *)dwUser; + DWORD last_playpos, playpos; + PIDSCDRIVERBUFFER iface = (PIDSCDRIVERBUFFER)This; + + /* **** */ + EnterCriticalSection(&This->pcm_crst); + + IDsDriverBuffer_GetPosition(iface, &playpos, NULL); + last_playpos = This->notify->playpos; + This->notify->playpos = playpos; + + if (snd_pcm_state(This->pcm) != SND_PCM_STATE_RUNNING || last_playpos == playpos || !This->notify->nrofnotifies || !This->notify->notifies) + goto done; + + if (playpos < last_playpos) + { + Capture_CheckNotify(This->notify, last_playpos, This->mmap_buflen_bytes); + if (playpos) + Capture_CheckNotify(This->notify, 0, playpos); + } + else Capture_CheckNotify(This->notify, last_playpos, playpos - last_playpos); + +done: + LeaveCriticalSection(&This->pcm_crst); + /* **** */ +} + +static HRESULT WINAPI IDsCaptureDriverNotifyImpl_QueryInterface(PIDSDRIVERNOTIFY iface, REFIID riid, LPVOID *ppobj) +{ + IDsCaptureDriverNotifyImpl *This = (IDsCaptureDriverNotifyImpl *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + + if ( IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IDsDriverNotify) ) { + IDsDriverNotify_AddRef(iface); + *ppobj = This; + return DS_OK; + } + + FIXME( "Unknown IID %s\n", debugstr_guid(riid)); + + *ppobj = 0; + return E_NOINTERFACE; +} + +static ULONG WINAPI IDsCaptureDriverNotifyImpl_AddRef(PIDSDRIVERNOTIFY iface) +{ + IDsCaptureDriverNotifyImpl *This = (IDsCaptureDriverNotifyImpl *)iface; + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref was %d\n", This, refCount - 1); + + return refCount; +} + +static ULONG WINAPI IDsCaptureDriverNotifyImpl_Release(PIDSDRIVERNOTIFY iface) +{ + IDsCaptureDriverNotifyImpl *This = (IDsCaptureDriverNotifyImpl *)iface; + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref was %d\n", This, refCount + 1); + + if (!refCount) { + This->buffer->notify = NULL; + if (This->timerID) + { + timeKillEvent(This->timerID); + timeEndPeriod(DS_TIME_RES); + } + HeapFree(GetProcessHeap(), 0, This->notifies); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return refCount; +} + +static HRESULT WINAPI IDsCaptureDriverNotifyImpl_SetNotificationPositions(PIDSDRIVERNOTIFY iface, DWORD howmuch, LPCDSBPOSITIONNOTIFY notify) +{ + DWORD len = howmuch * sizeof(DSBPOSITIONNOTIFY); + unsigned i; + LPVOID notifies; + IDsCaptureDriverNotifyImpl *This = (IDsCaptureDriverNotifyImpl *)iface; + TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify); + + if (!notify) { + WARN("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } + + if (TRACE_ON(dsalsa)) + for (i=0;ibuffer->pcm_crst); + + /* Make an internal copy of the caller-supplied array. + * Replace the existing copy if one is already present. */ + if (This->notifies) + notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->notifies, len); + else + notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); + + if (!notifies) + { + LeaveCriticalSection(&This->buffer->pcm_crst); + /* **** */ + return DSERR_OUTOFMEMORY; + } + This->notifies = notifies; + memcpy(This->notifies, notify, len); + This->nrofnotifies = howmuch; + IDsDriverBuffer_GetPosition((PIDSCDRIVERBUFFER)This->buffer, &This->playpos, NULL); + + if (!This->timerID) + { + timeBeginPeriod(DS_TIME_RES); + This->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, Capture_Notify, (DWORD_PTR)This->buffer, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS); + } + + LeaveCriticalSection(&This->buffer->pcm_crst); + /* **** */ + + return S_OK; +} + +static const IDsDriverNotifyVtbl dscdnvt = +{ + IDsCaptureDriverNotifyImpl_QueryInterface, + IDsCaptureDriverNotifyImpl_AddRef, + IDsCaptureDriverNotifyImpl_Release, + IDsCaptureDriverNotifyImpl_SetNotificationPositions, +}; + #if 0 /** Convert the position an application sees into a position ALSA sees */ static snd_pcm_uframes_t fakepos_to_realpos(const IDsCaptureDriverBufferImpl* This, DWORD fakepos) @@ -302,8 +474,37 @@ static int CreateMMAP(IDsCaptureDriverBufferImpl* pdbi) static HRESULT WINAPI IDsCaptureDriverBufferImpl_QueryInterface(PIDSCDRIVERBUFFER iface, REFIID riid, LPVOID *ppobj) { - /* IDsCaptureDriverBufferImpl *This = (IDsCaptureDriverBufferImpl *)iface; */ - FIXME("(): stub!\n"); + IDsCaptureDriverBufferImpl *This = (IDsCaptureDriverBufferImpl *)iface; + if ( IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IDsCaptureDriverBuffer) ) { + IDsCaptureDriverBuffer_AddRef(iface); + *ppobj = (LPVOID)iface; + return DS_OK; + } + + if ( IsEqualGUID( &IID_IDsDriverNotify, riid ) ) { + if (!This->notify) + { + This->notify = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDsCaptureDriverNotifyImpl)); + if (!This->notify) + return DSERR_OUTOFMEMORY; + This->notify->lpVtbl = &dscdnvt; + This->notify->buffer = This; + + /* Keep a lock on IDsDriverNotify for ourself, so it is destroyed when the buffer is */ + IDsDriverNotify_AddRef((PIDSDRIVERNOTIFY)This->notify); + } + IDsDriverNotify_AddRef((PIDSDRIVERNOTIFY)This->notify); + *ppobj = (LPVOID)This->notify; + return DS_OK; + } + + if ( IsEqualGUID( &IID_IDsDriverPropertySet, riid ) ) { + FIXME("Unsupported interface IID_IDsDriverPropertySet\n"); + return E_FAIL; + } + + FIXME("(): Unknown interface %s\n", debugstr_guid(riid)); return DSERR_UNSUPPORTED; } @@ -327,6 +528,9 @@ static ULONG WINAPI IDsCaptureDriverBufferImpl_Release(PIDSCDRIVERBUFFER iface) if (refCount) return refCount; + EnterCriticalSection(&This->pcm_crst); + if (This->notify) + IDsDriverNotify_Release((PIDSDRIVERNOTIFY)This->notify); TRACE("mmap buffer %p destroyed\n", This->mmap_buffer); This->drv->capture_buffer = NULL; @@ -445,7 +649,7 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_SetFormat(PIDSCDRIVERBUFFER ifa } snd_pcm_hw_params_set_periods_integer(pcm, hw_params); - buffer_size = snd_pcm_bytes_to_frames(pcm, This->mmap_buflen_bytes); + buffer_size = This->mmap_buflen_bytes / pwfx->nBlockAlign; snd_pcm_hw_params_set_buffer_size_near(pcm, hw_params, &buffer_size); buffer_size = 5000; snd_pcm_hw_params_set_period_time_near(pcm, hw_params, (unsigned int*)&buffer_size, NULL); @@ -563,6 +767,15 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_Start(PIDSCDRIVERBUFFER iface, * what it does right now is fill the buffer once.. ALSA size */ FIXME("Non-looping buffers are not properly supported!\n"); CommitAll(This, TRUE); + + if (This->notify && This->notify->nrofnotifies && This->notify->notifies) + { + DWORD playpos = realpos_to_fakepos(This, This->mmap_pos); + if (playpos) + Capture_CheckNotify(This->notify, 0, playpos); + This->notify->playpos = playpos; + } + /* **** */ LeaveCriticalSection(&This->pcm_crst); return DS_OK; @@ -578,6 +791,10 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_Stop(PIDSCDRIVERBUFFER iface) This->play_looping = FALSE; snd_pcm_drop(This->pcm); snd_pcm_prepare(This->pcm); + + if (This->notify && This->notify->notifies && This->notify->nrofnotifies) + Capture_CheckNotify(This->notify, 0, 0); + /* **** */ LeaveCriticalSection(&This->pcm_crst); return DS_OK; diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index 8035abb0f40..12dc0c1f290 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -198,6 +198,7 @@ HRESULT shader_get_registers_used( char pshader = shader_is_pshader_version(This->baseShader.hex_version); reg_maps->bumpmat = -1; + reg_maps->luminanceparams = -1; if (pToken == NULL) return WINED3D_OK; @@ -354,11 +355,15 @@ HRESULT shader_get_registers_used( } /* texbem is only valid with < 1.4 pixel shaders */ - if(WINED3DSIO_TEXBEM == curOpcode->opcode) { + if(WINED3DSIO_TEXBEM == curOpcode->opcode || + WINED3DSIO_TEXBEML == curOpcode->opcode) { if(reg_maps->bumpmat != -1 && reg_maps->bumpmat != sampler_code) { FIXME("Pixel shader uses texbem instruction on more than 1 sampler\n"); } else { reg_maps->bumpmat = sampler_code; + if(WINED3DSIO_TEXBEML == curOpcode->opcode) { + reg_maps->luminanceparams = sampler_code; + } } } } diff --git a/dlls/wined3d/basetexture.c b/dlls/wined3d/basetexture.c index 8df0b3e8bc3..a1290f869ce 100644 --- a/dlls/wined3d/basetexture.c +++ b/dlls/wined3d/basetexture.c @@ -161,11 +161,39 @@ DWORD WINAPI IWineD3DBaseTextureImpl_GetLevelCount(IWineD3DBaseTexture *iface) { HRESULT WINAPI IWineD3DBaseTextureImpl_SetAutoGenFilterType(IWineD3DBaseTexture *iface, WINED3DTEXTUREFILTERTYPE FilterType) { IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + UINT textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface); if (!(This->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)) { TRACE("(%p) : returning invalid call\n", This); return WINED3DERR_INVALIDCALL; } + if(This->baseTexture.filterType != FilterType) { + /* What about multithreading? Do we want all the context overhead just to set this value? + * Or should we delay the applying until the texture is used for drawing? For now, apply + * immediately. + */ + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); + glBindTexture(textureDimensions, This->baseTexture.textureName); + checkGLcall("glBindTexture"); + switch(FilterType) { + case WINED3DTEXF_NONE: + case WINED3DTEXF_POINT: + glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST); + checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST)"); + + case WINED3DTEXF_LINEAR: + glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); + checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST)"); + + default: + WARN("Unexpected filter type %d, setting to GL_NICEST\n", FilterType); + glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); + checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST)"); + } + LEAVE_GL(); + } This->baseTexture.filterType = FilterType; TRACE("(%p) :\n", This); return WINED3D_OK; @@ -239,6 +267,16 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) { This->baseTexture.states[WINED3DTEXSTA_TSSADDRESSW] = WINED3DTADDRESS_WRAP; IWineD3DBaseTexture_SetDirty(iface, TRUE); isNewTexture = TRUE; + + if(This->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP) { + /* This means double binding the texture at creation, but keeps the code simpler all + * in all, and the run-time path free from additional checks + */ + glBindTexture(textureDimensions, This->baseTexture.textureName); + checkGLcall("glBindTexture"); + glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_SGIS, GL_TRUE)"); + } } /* Bind the texture */ diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 10f81e51c10..4c2b3963256 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -882,7 +882,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY); /* Calculate levels for mip mapping */ - if (Levels == 0) { + if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) { + if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + if(Levels > 1) { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + object->baseTexture.levels = 1; + } else if (Levels == 0) { TRACE("calculating levels %d\n", object->baseTexture.levels); object->baseTexture.levels++; tmpW = Width; @@ -956,7 +966,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa object->depth = Depth; /* Calculate levels for mip mapping */ - if (Levels == 0) { + if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) { + if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + if(Levels > 1) { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + Levels = 1; + } else if (Levels == 0) { object->baseTexture.levels++; tmpW = Width; tmpH = Height; @@ -1076,7 +1096,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength); /* Calculate levels for mip mapping */ - if (Levels == 0) { + if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) { + if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + if(Levels > 1) { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + Levels = 1; + } else if (Levels == 0) { object->baseTexture.levels++; tmpW = EdgeLength; while (tmpW > 1) { diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 774bf38e30b..e77a237f8b1 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -117,6 +117,9 @@ static const struct { {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1}, {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2}, {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3}, + + /* SGI */ + {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP}, }; /********************************************************** @@ -1477,6 +1480,13 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt } } + if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) { + if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { + TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } + /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */ @@ -1688,7 +1698,8 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt return WINED3D_OK; /***** - * Not supported for now: Bump mapping formats + * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or + * GL_NV_texture_shader), but advertized to make apps happy. * Enable some because games often fail when they are not available * and are still playable even without bump mapping */ @@ -1697,11 +1708,19 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt case WINED3DFMT_L6V5U5: case WINED3DFMT_X8L8V8U8: case WINED3DFMT_Q8W8V8U8: - case WINED3DFMT_W11V11U10: - case WINED3DFMT_A2W10V10U10: WARN_(d3d_caps)("[Not supported, but pretended to do]\n"); return WINED3D_OK; + /* Those are not advertized by the nvidia windows driver, and not + * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap. + * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned + * ARGB format if needed + */ + case WINED3DFMT_W11V11U10: + case WINED3DFMT_A2W10V10U10: + WARN_(d3d_caps)("[FAILED]\n"); + return WINED3DERR_NOTAVAILABLE; + /***** * DXTN Formats: Handled above * WINED3DFMT_DXT1 diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 2343f738103..9155a453eac 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -389,7 +389,25 @@ void shader_glsl_load_constants( pos = GL_EXTCALL(glGetUniformLocationARB(programId, "bumpenvmat")); checkGLcall("glGetUniformLocationARB"); GL_EXTCALL(glUniformMatrix2fvARB(pos, 1, 0, data)); - checkGLcall("glUniform4fvARB"); + checkGLcall("glUniformMatrix2fvARB"); + + /* texbeml needs the luminance scale and offset too. If texbeml is used, needsbumpmat + * is set too, so we can check that in the needsbumpmat check + */ + if(((IWineD3DPixelShaderImpl *) pshader)->baseShader.reg_maps.luminanceparams != -1) { + int stage = ((IWineD3DPixelShaderImpl *) pshader)->baseShader.reg_maps.luminanceparams; + GLfloat *scale = (GLfloat *) &stateBlock->textureState[stage][WINED3DTSS_BUMPENVLSCALE]; + GLfloat *offset = (GLfloat *) &stateBlock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET]; + + pos = GL_EXTCALL(glGetUniformLocationARB(programId, "luminancescale")); + checkGLcall("glGetUniformLocationARB"); + GL_EXTCALL(glUniform1fvARB(pos, 1, scale)); + checkGLcall("glUniform1fvARB"); + pos = GL_EXTCALL(glGetUniformLocationARB(programId, "luminanceoffset")); + checkGLcall("glGetUniformLocationARB"); + GL_EXTCALL(glUniform1fvARB(pos, 1, offset)); + checkGLcall("glUniform1fvARB"); + } } } } @@ -429,8 +447,13 @@ void shader_generate_glsl_declarations( if(!pshader) shader_addline(buffer, "uniform vec4 posFixup;\n"); - else if(reg_maps->bumpmat != -1) + else if(reg_maps->bumpmat != -1) { shader_addline(buffer, "uniform mat2 bumpenvmat;\n"); + if(reg_maps->luminanceparams) { + shader_addline(buffer, "uniform float luminancescale;\n"); + shader_addline(buffer, "uniform float luminanceoffset;\n"); + } + } /* Declare texture samplers */ for (i = 0; i < This->baseShader.limits.sampler; i++) { @@ -1974,8 +1997,16 @@ void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) { shader_glsl_append_dst(arg->buffer, arg); shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &coord_param); - shader_addline(arg->buffer, "%s(Psampler%u, T%u%s + vec4(bumpenvmat * %s, 0.0, 0.0)%s )%s);\n", - sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, dst_swizzle); + if(arg->opcode->opcode == WINED3DSIO_TEXBEML) { + glsl_src_param_t luminance_param; + shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_2, &luminance_param); + shader_addline(arg->buffer, "(%s(Psampler%u, T%u%s + vec4(bumpenvmat * %s, 0.0, 0.0)%s )*(%s * luminancescale + luminanceoffset))%s);\n", + sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, + luminance_param.param_str, dst_swizzle); + } else { + shader_addline(arg->buffer, "%s(Psampler%u, T%u%s + vec4(bumpenvmat * %s, 0.0, 0.0)%s )%s);\n", + sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, dst_swizzle); + } } void pshader_glsl_bem(SHADER_OPCODE_ARG* arg) { diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 3209f61e5ae..0bcbdce55a5 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -223,7 +223,7 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { {WINED3DSIO_TEX, "texld", "undefined", 1, 2, pshader_hw_tex, pshader_glsl_tex, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)}, {WINED3DSIO_TEX, "texld", "undefined", 1, 3, pshader_hw_tex, pshader_glsl_tex, WINED3DPS_VERSION(2,0), -1}, {WINED3DSIO_TEXBEM, "texbem", "undefined", 1, 2, pshader_hw_texbem, pshader_glsl_texbem, 0, WINED3DPS_VERSION(1,3)}, - {WINED3DSIO_TEXBEML, "texbeml", GLNAME_REQUIRE_GLSL, 1, 2, NULL, NULL, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)}, + {WINED3DSIO_TEXBEML, "texbeml", GLNAME_REQUIRE_GLSL, 1, 2, pshader_hw_texbem, pshader_glsl_texbem, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)}, {WINED3DSIO_TEXREG2AR,"texreg2ar","undefined", 1, 2, pshader_hw_texreg2ar, pshader_glsl_texreg2ar, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)}, {WINED3DSIO_TEXREG2GB,"texreg2gb","undefined", 1, 2, pshader_hw_texreg2gb, pshader_glsl_texreg2gb, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)}, {WINED3DSIO_TEXREG2RGB, "texreg2rgb", GLNAME_REQUIRE_GLSL, 1, 2, NULL, pshader_glsl_texreg2rgb, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)}, diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 2da7bd893f7..9737f2b9d87 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -2139,6 +2139,20 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine } } +static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; + + /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them + * has an update pending + */ + if(isStateDirty(context, STATE_VDECL) || + isStateDirty(context, STATE_PIXELSHADER)) { + return; + } + + device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device)); +} + static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; union { @@ -2146,6 +2160,17 @@ static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, W float f; } tmpvalue; + if(stateblock->pixelShader && stage != 0 && + ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) { + /* The pixel shader has to know the luminance scale. Do a constants update if it + * isn't scheduled anyway + */ + if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) && + !isStateDirty(context, STATE_PIXELSHADER)) { + shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context); + } + } + tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE]; if(tmpvalue.f != 0.0) { FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n"); @@ -2159,6 +2184,17 @@ static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, float f; } tmpvalue; + if(stateblock->pixelShader && stage != 0 && + ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) { + /* The pixel shader has to know the luminance offset. Do a constants update if it + * isn't scheduled anyway + */ + if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) && + !isStateDirty(context, STATE_PIXELSHADER)) { + shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context); + } + } + tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET]; if(tmpvalue.f != 0.0) { FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n"); @@ -2278,20 +2314,6 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont } } -static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; - - /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them - * has an update pending - */ - if(isStateDirty(context, STATE_VDECL) || - isStateDirty(context, STATE_PIXELSHADER)) { - return; - } - - device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device)); -} - static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; BOOL use_pshader = use_ps(device); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index aecf7f27873..c41e2ebda93 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -696,36 +696,19 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED This->Flags &= ~SFLAG_INSYSMEM; /* This is the marker that surface data has to be downloaded */ } - /* Calculate the correct start address to report */ + /* Calculate the dimensions of the locked rect */ if (NULL == pRect) { - pLockedRect->pBits = This->resource.allocatedMemory; This->lockedRect.left = 0; This->lockedRect.top = 0; This->lockedRect.right = This->currentDesc.Width; This->lockedRect.bottom = This->currentDesc.Height; TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n", &This->lockedRect, This->lockedRect.left, This->lockedRect.top, This->lockedRect.right, This->lockedRect.bottom); } else { - TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom); - - /* DXTn textures are based on compressed blocks of 4x4 pixels, each - * 16 bytes large (8 bytes in case of DXT1). Because of that Pitch has - * slightly different meaning compared to regular textures. For DXTn - * textures Pitch is the size of a row of blocks, 4 high and "width" - * long. The x offset is calculated differently as well, since moving 4 - * pixels to the right actually moves an entire 4x4 block to right, ie - * 16 bytes (8 in case of DXT1). */ - if (This->resource.format == WINED3DFMT_DXT1) { - pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top / 4) + (pRect->left * 2); - } else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 - || This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) { - pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top / 4) + (pRect->left * 4); - } else { - pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel); - } This->lockedRect.left = pRect->left; This->lockedRect.top = pRect->top; This->lockedRect.right = pRect->right; This->lockedRect.bottom = pRect->bottom; + TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom); } if (This->Flags & SFLAG_NONPOW2) { @@ -872,6 +855,27 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED } lock_end: + /* Calculate the correct start address to report */ + if (NULL == pRect) { + pLockedRect->pBits = This->resource.allocatedMemory; + } else { + /* DXTn textures are based on compressed blocks of 4x4 pixels, each + * 16 bytes large (8 bytes in case of DXT1). Because of that Pitch has + * slightly different meaning compared to regular textures. For DXTn + * textures Pitch is the size of a row of blocks, 4 high and "width" + * long. The x offset is calculated differently as well, since moving 4 + * pixels to the right actually moves an entire 4x4 block to right, ie + * 16 bytes (8 in case of DXT1). */ + if (This->resource.format == WINED3DFMT_DXT1) { + pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top / 4) + (pRect->left * 2); + } else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 + || This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) { + pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top / 4) + (pRect->left * 4); + } else { + pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel); + } + } + if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) { /* Don't dirtify */ } else { @@ -1572,6 +1576,20 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ *target_bpp = 3; break; + case WINED3DFMT_L6V5U5: + *convert = CONVERT_L6V5U5; + if(GL_SUPPORT(NV_TEXTURE_SHADER)) { + *target_bpp = 3; + /* Use format and types from table */ + } else { + /* Load it into unsigned R5G6B5, swap L and V channels, and revert that in the shader */ + *target_bpp = 2; + *format = GL_RGB; + *internal = GL_RGB5; + *type = GL_UNSIGNED_SHORT_5_6_5; + } + break; + case WINED3DFMT_X8L8V8U8: *convert = CONVERT_X8L8V8U8; *target_bpp = 4; @@ -1834,6 +1852,46 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN break; } + case CONVERT_L6V5U5: + { + unsigned int x, y; + WORD *Source; + unsigned char *Dest; + + if(GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* This makes the gl surface bigger(24 bit instead of 16), but it works with + * fixed function and shaders without further conversion once the surface is + * loaded + */ + for(y = 0; y < height; y++) { + Source = (WORD *) (src + y * pitch); + Dest = (unsigned char *) (dst + y * outpitch); + for (x = 0; x < width; x++ ) { + short color = (*Source++); + unsigned char l = ((color >> 10) & 0xfc); + char v = ((color >> 5) & 0x3e); + char u = ((color ) & 0x1f); + + /* 8 bits destination, 6 bits source, 8th bit is the sign. gl ignores the sign + * and doubles the positive range. Thus shift left only once, gl does the 2nd + * shift. GL reads a signed value and converts it into an unsigned value. + */ + /* M */ Dest[2] = l << 1; + + /* Those are read as signed, but kept signed. Just left-shift 3 times to scale + * from 5 bit values to 8 bit values. + */ + /* V */ Dest[1] = v << 3; + /* U */ Dest[0] = u << 3; + Dest += 3; + } + } + } else { + FIXME("Add D3DFMT_L6V5U5 emulation using standard unsigned RGB and shaders\n"); + } + break; + } + case CONVERT_X8L8V8U8: { unsigned int x, y; diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 472907fbc1f..d5131e17b2a 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -169,7 +169,7 @@ static const GlPixelFormatDescTemplate gl_formats_template[] = { {WINED3DFMT_A4L4 ,GL_LUMINANCE4_ALPHA4 ,GL_LUMINANCE4_ALPHA4 ,GL_LUMINANCE_ALPHA ,GL_UNSIGNED_BYTE }, /* Bump mapping stuff */ {WINED3DFMT_V8U8 ,GL_DSDT8_NV ,GL_DSDT8_NV ,GL_DSDT_NV ,GL_BYTE }, - {WINED3DFMT_L6V5U5 ,GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX ,GL_UNSIGNED_SHORT_5_5_5_1 }, + {WINED3DFMT_L6V5U5 ,GL_DSDT8_MAG8_NV ,GL_DSDT8_MAG8_NV ,GL_DSDT_MAG_NV ,GL_BYTE }, {WINED3DFMT_X8L8V8U8 ,GL_DSDT8_MAG8_INTENSITY8_NV ,GL_DSDT8_MAG8_INTENSITY8_NV ,GL_DSDT_MAG_VIB_NV ,GL_UNSIGNED_INT_8_8_S8_S8_REV_NV}, {WINED3DFMT_Q8W8V8U8 ,GL_SIGNED_RGBA8_NV ,GL_SIGNED_RGBA8_NV ,GL_RGBA ,GL_BYTE }, {WINED3DFMT_V16U16 ,GL_SIGNED_HILO16_NV ,GL_SIGNED_HILO16_NV ,GL_HILO_NV ,GL_SHORT }, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 27ef55333d3..0ed2d5db458 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1231,6 +1231,7 @@ typedef enum { CONVERT_CK_8888_ARGB, CONVERT_RGB32_888, CONVERT_V8U8, + CONVERT_L6V5U5, CONVERT_X8L8V8U8, CONVERT_Q8W8V8U8, CONVERT_V16U16, @@ -1656,7 +1657,7 @@ typedef struct shader_reg_maps { /* Sampler usage tokens * Use 0 as default (bit 31 is always 1 on a valid token) */ DWORD samplers[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)]; - char bumpmat; + char bumpmat, luminanceparams; /* Whether or not a loop is used in this shader */ char loop; diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index f6216b66019..3dab1b643f1 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -149,6 +149,7 @@ static int WineGLExtensionListSize; static WineGLPixelFormat *WineGLPixelFormatList; static int WineGLPixelFormatListSize = 0; +static int WineGLPixelFormatOnScreenSize = 0; static void X11DRV_WineGL_LoadExtensions(void); static BOOL glxRequireVersion(int requiredVersion); @@ -544,6 +545,7 @@ static inline void free_context(Wine_GLContext *context) if (context->prev != NULL) context->prev->next = context->next; else context_list = context->next; + if (context->vis) XFree(context->vis); HeapFree(GetProcessHeap(), 0, context); } @@ -854,6 +856,7 @@ static BOOL init_formats(Display *display, int screen, Visual *visual) WineGLPixelFormatList[0].render_type = get_render_type_from_fbconfig(display, fbconfig); WineGLPixelFormatList[0].offscreenOnly = FALSE; WineGLPixelFormatListSize = 1; + WineGLPixelFormatOnScreenSize = 1; /* Fill the list with offscreen formats */ for(i=0; i WineGLPixelFormatListSize)) { - if(AllowOffscreen) - *fmt_count = WineGLPixelFormatListSize; - else - *fmt_count = 1; /* Only show the format of our main visual */ - } - else if(iPixelFormat == 1) { - res = &WineGLPixelFormatList[0]; - *fmt_count = 1; /* Only show the format of our main visual */ - } - else if((WineGLPixelFormatList[iPixelFormat-1].offscreenOnly == TRUE) && AllowOffscreen) { + if((iPixelFormat > 0) && (iPixelFormat <= WineGLPixelFormatListSize) && + ((WineGLPixelFormatList[iPixelFormat-1].offscreenOnly == FALSE) || + AllowOffscreen)) { res = &WineGLPixelFormatList[iPixelFormat-1]; - *fmt_count = WineGLPixelFormatListSize; TRACE("Returning FBConfig=%p for iPixelFormat=%d\n", res->fbconfig, iPixelFormat); } + if(AllowOffscreen) + *fmt_count = WineGLPixelFormatListSize; + else + *fmt_count = WineGLPixelFormatOnScreenSize; + TRACE("Number of returned pixelformats=%d\n", *fmt_count); return res; @@ -1035,6 +1034,8 @@ int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev, bestFormat = i; continue; } + if(bestDBuffer != -1 && (dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) + continue; } /* Stereo, see the comments above. */ @@ -1052,6 +1053,8 @@ int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev, bestFormat = i; continue; } + if(bestStereo != -1 && (dwFlags & PFD_STEREO) != bestStereo) + continue; } /* Below we will do a number of checks to select the 'best' pixelformat. @@ -1371,22 +1374,6 @@ BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, if (TRACE_ON(opengl)) { int gl_test = 0; - /* - * How to test if hdc current drawable is compatible (visual/FBConfig) ? - * - * in case of root window created HDCs we crash here :( - * - Drawable drawable = get_drawable( physDev->hdc ); - TRACE(" drawable (%p,%p) have :\n", drawable, root_window); - pglXQueryDrawable(gdi_display, drawable, GLX_FBCONFIG_ID, (unsigned int*) &value); - TRACE(" - FBCONFIG_ID as 0x%x\n", tmp); - pglXQueryDrawable(gdi_display, drawable, GLX_VISUAL_ID, (unsigned int*) &value); - TRACE(" - VISUAL_ID as 0x%x\n", tmp); - pglXQueryDrawable(gdi_display, drawable, GLX_WIDTH, (unsigned int*) &value); - TRACE(" - WIDTH as %d\n", tmp); - pglXQueryDrawable(gdi_display, drawable, GLX_HEIGHT, (unsigned int*) &value); - TRACE(" - HEIGHT as %d\n", tmp); - */ gl_test = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_FBCONFIG_ID, &value); if (gl_test) { ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); @@ -1413,8 +1400,6 @@ HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) WineGLPixelFormat *fmt; int hdcPF = physDev->current_pf; int fmt_count = 0; - int value = 0; - int gl_test = 0; HDC hdc = physDev->hdc; TRACE("(%p)->(PF:%d)\n", hdc, hdcPF); @@ -1424,9 +1409,6 @@ HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) return 0; } - /* First, get the visual in use by the X11DRV */ - if (!gdi_display) return 0; - fmt = ConvertPixelFormatWGLtoGLX(gdi_display, hdcPF, TRUE /* Offscreen */, &fmt_count); /* We can render using the iPixelFormat (1) of Wine's Main visual AND using some offscreen formats. * Note that standard WGL-calls don't recognize offscreen-only formats. For that reason pbuffers @@ -1438,19 +1420,6 @@ HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) return NULL; } - if (fmt_count < hdcPF) { - ERR("(%p): unexpected pixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, hdcPF, fmt_count); - SetLastError(ERROR_INVALID_PIXEL_FORMAT); - return NULL; - } - - gl_test = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_FBCONFIG_ID, &value); - if (gl_test) { - ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); - SetLastError(ERROR_INVALID_PIXEL_FORMAT); - return NULL; - } - /* The context will be allocated in the wglMakeCurrent call */ wine_tsx11_lock(); ret = alloc_context(); diff --git a/dlls/wintrust/softpub.c b/dlls/wintrust/softpub.c index a590db747de..48632d59b5c 100644 --- a/dlls/wintrust/softpub.c +++ b/dlls/wintrust/softpub.c @@ -16,6 +16,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include + +#define NONAMELESSUNION + #include "windef.h" #include "winbase.h" #include "wintrust.h" @@ -37,7 +40,7 @@ HRESULT WINAPI SoftpubInitialize(CRYPT_PROVIDER_DATA *data) return ret; } -/* Assumes data->pWintrustData->pFile exists. Makes sure a file handle is +/* Assumes data->pWintrustData->u.pFile exists. Makes sure a file handle is * open for the file. */ static BOOL SOFTPUB_OpenFile(CRYPT_PROVIDER_DATA *data) @@ -48,13 +51,13 @@ static BOOL SOFTPUB_OpenFile(CRYPT_PROVIDER_DATA *data) * typically have hFile as NULL rather than INVALID_HANDLE_VALUE. Check * for both. */ - if (!data->pWintrustData->pFile->hFile || - data->pWintrustData->pFile->hFile == INVALID_HANDLE_VALUE) + if (!data->pWintrustData->u.pFile->hFile || + data->pWintrustData->u.pFile->hFile == INVALID_HANDLE_VALUE) { - data->pWintrustData->pFile->hFile = - CreateFileW(data->pWintrustData->pFile->pcwszFilePath, GENERIC_READ, + data->pWintrustData->u.pFile->hFile = + CreateFileW(data->pWintrustData->u.pFile->pcwszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (data->pWintrustData->pFile->hFile != INVALID_HANDLE_VALUE) + if (data->pWintrustData->u.pFile->hFile != INVALID_HANDLE_VALUE) data->fOpenedFile = TRUE; else ret = FALSE; @@ -63,40 +66,40 @@ static BOOL SOFTPUB_OpenFile(CRYPT_PROVIDER_DATA *data) return ret; } -/* Assumes data->pWintrustData->pFile exists. Sets data->pPDSip->gSubject to +/* Assumes data->pWintrustData->u.pFile exists. Sets data->pPDSip->gSubject to * the file's subject GUID. */ static BOOL SOFTPUB_GetFileSubject(CRYPT_PROVIDER_DATA *data) { BOOL ret; - if (!data->pWintrustData->pFile->pgKnownSubject) + if (!data->pWintrustData->u.pFile->pgKnownSubject) { ret = CryptSIPRetrieveSubjectGuid( - data->pWintrustData->pFile->pcwszFilePath, - data->pWintrustData->pFile->hFile, - &data->pPDSip->gSubject); + data->pWintrustData->u.pFile->pcwszFilePath, + data->pWintrustData->u.pFile->hFile, + &data->u.pPDSip->gSubject); } else { - memcpy(&data->pPDSip->gSubject, - data->pWintrustData->pFile->pgKnownSubject, sizeof(GUID)); + memcpy(&data->u.pPDSip->gSubject, + data->pWintrustData->u.pFile->pgKnownSubject, sizeof(GUID)); ret = TRUE; } TRACE("returning %d\n", ret); return ret; } -/* Assumes data->pPDSip exists, and its gSubject member set. - * Allocates data->pPDSip->pSip and loads it, if possible. +/* Assumes data->u.pPDSip exists, and its gSubject member set. + * Allocates data->u.pPDSip->pSip and loads it, if possible. */ static BOOL SOFTPUB_GetSIP(CRYPT_PROVIDER_DATA *data) { BOOL ret; - data->pPDSip->pSip = data->psPfns->pfnAlloc(sizeof(SIP_DISPATCH_INFO)); - if (data->pPDSip->pSip) - ret = CryptSIPLoad(&data->pPDSip->gSubject, 0, data->pPDSip->pSip); + data->u.pPDSip->pSip = data->psPfns->pfnAlloc(sizeof(SIP_DISPATCH_INFO)); + if (data->u.pPDSip->pSip) + ret = CryptSIPLoad(&data->u.pPDSip->gSubject, 0, data->u.pPDSip->pSip); else { SetLastError(ERROR_OUTOFMEMORY); @@ -106,8 +109,8 @@ static BOOL SOFTPUB_GetSIP(CRYPT_PROVIDER_DATA *data) return ret; } -/* Assumes data->pPDSip has been loaded, and data->pPDSip->pSip allocated. - * Calls data->pPDSip->pSip->pfGet to construct data->hMsg. +/* Assumes data->u.pPDSip has been loaded, and data->u.pPDSip->pSip allocated. + * Calls data->u.pPDSip->pSip->pfGet to construct data->hMsg. */ static BOOL SOFTPUB_GetMessageFromFile(CRYPT_PROVIDER_DATA *data) { @@ -115,21 +118,21 @@ static BOOL SOFTPUB_GetMessageFromFile(CRYPT_PROVIDER_DATA *data) LPBYTE buf = NULL; DWORD size = 0; - data->pPDSip->psSipSubjectInfo = + data->u.pPDSip->psSipSubjectInfo = data->psPfns->pfnAlloc(sizeof(SIP_SUBJECTINFO)); - if (!data->pPDSip->psSipSubjectInfo) + if (!data->u.pPDSip->psSipSubjectInfo) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } - data->pPDSip->psSipSubjectInfo->cbSize = sizeof(SIP_SUBJECTINFO); - data->pPDSip->psSipSubjectInfo->pgSubjectType = &data->pPDSip->gSubject; - data->pPDSip->psSipSubjectInfo->hFile = data->pWintrustData->pFile->hFile; - data->pPDSip->psSipSubjectInfo->pwsFileName = - data->pWintrustData->pFile->pcwszFilePath; - data->pPDSip->psSipSubjectInfo->hProv = data->hProv; - ret = data->pPDSip->pSip->pfGet(data->pPDSip->psSipSubjectInfo, + data->u.pPDSip->psSipSubjectInfo->cbSize = sizeof(SIP_SUBJECTINFO); + data->u.pPDSip->psSipSubjectInfo->pgSubjectType = &data->u.pPDSip->gSubject; + data->u.pPDSip->psSipSubjectInfo->hFile = data->pWintrustData->u.pFile->hFile; + data->u.pPDSip->psSipSubjectInfo->pwsFileName = + data->pWintrustData->u.pFile->pcwszFilePath; + data->u.pPDSip->psSipSubjectInfo->hProv = data->hProv; + ret = data->u.pPDSip->pSip->pfGet(data->u.pPDSip->psSipSubjectInfo, &data->dwEncoding, 0, &size, 0); if (!ret) { @@ -144,7 +147,7 @@ static BOOL SOFTPUB_GetMessageFromFile(CRYPT_PROVIDER_DATA *data) return FALSE; } - ret = data->pPDSip->pSip->pfGet(data->pPDSip->psSipSubjectInfo, + ret = data->u.pPDSip->pSip->pfGet(data->u.pPDSip->psSipSubjectInfo, &data->dwEncoding, 0, &size, buf); if (ret) { @@ -217,8 +220,8 @@ static DWORD SOFTPUB_DecodeInnerContent(CRYPT_PROVIDER_DATA *data) SPC_INDIRECT_DATA_CONTENT_STRUCT, buf, size, 0, NULL, &size); if (!ret) goto error; - data->pPDSip->psIndirectData = data->psPfns->pfnAlloc(size); - if (!data->pPDSip->psIndirectData) + data->u.pPDSip->psIndirectData = data->psPfns->pfnAlloc(size); + if (!data->u.pPDSip->psIndirectData) { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; @@ -226,7 +229,7 @@ static DWORD SOFTPUB_DecodeInnerContent(CRYPT_PROVIDER_DATA *data) } ret = CryptDecodeObject(data->dwEncoding, SPC_INDIRECT_DATA_CONTENT_STRUCT, buf, size, 0, - data->pPDSip->psIndirectData, &size); + data->u.pPDSip->psIndirectData, &size); } else { @@ -256,7 +259,7 @@ HRESULT WINAPI SoftpubLoadMessage(CRYPT_PROVIDER_DATA *data) ret = TRUE; break; case WTD_CHOICE_FILE: - if (!data->pWintrustData->pFile) + if (!data->pWintrustData->u.pFile) { SetLastError(ERROR_INVALID_PARAMETER); ret = FALSE; diff --git a/dlls/wintrust/tests/asn.c b/dlls/wintrust/tests/asn.c index 43b1cbacbb0..545e2102f94 100644 --- a/dlls/wintrust/tests/asn.c +++ b/dlls/wintrust/tests/asn.c @@ -68,7 +68,7 @@ static void test_encodeSPCLink(void) LocalFree(buf); } /* With an invalid char: */ - link.pwszUrl = (LPWSTR)nihongoURL; + U(link).pwszUrl = (LPWSTR)nihongoURL; size = 1; SetLastError(0xdeadbeef); ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link, @@ -79,7 +79,7 @@ static void test_encodeSPCLink(void) * index of the first invalid character. */ ok(size == 0, "Expected size 0, got %d\n", size); - link.pwszUrl = url; + U(link).pwszUrl = url; ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); @@ -90,7 +90,7 @@ static void test_encodeSPCLink(void) LocalFree(buf); } link.dwLinkChoice = SPC_FILE_LINK_CHOICE; - link.pwszFile = (LPWSTR)nihongoURL; + U(link).pwszFile = (LPWSTR)nihongoURL; ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); @@ -101,7 +101,7 @@ static void test_encodeSPCLink(void) LocalFree(buf); } link.dwLinkChoice = SPC_MONIKER_LINK_CHOICE; - memset(&link.Moniker, 0, sizeof(link.Moniker)); + memset(&U(link).Moniker, 0, sizeof(U(link).Moniker)); ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); @@ -111,9 +111,9 @@ static void test_encodeSPCLink(void) ok(!memcmp(buf, emptyMonikerSPCLink, size), "Unexpected value\n"); LocalFree(buf); } - memset(&link.Moniker.ClassId, 0xea, sizeof(link.Moniker.ClassId)); - link.Moniker.SerializedData.pbData = data; - link.Moniker.SerializedData.cbData = sizeof(data); + memset(&U(link).Moniker.ClassId, 0xea, sizeof(U(link).Moniker.ClassId)); + U(link).Moniker.SerializedData.pbData = data; + U(link).Moniker.SerializedData.cbData = sizeof(data); ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); @@ -145,7 +145,7 @@ static void test_decodeSPCLink(void) link = (SPC_LINK *)buf; ok(link->dwLinkChoice == SPC_URL_LINK_CHOICE, "Expected SPC_URL_LINK_CHOICE, got %d\n", link->dwLinkChoice); - ok(lstrlenW(link->pwszUrl) == 0, "Expected empty string\n"); + ok(lstrlenW(U(*link).pwszUrl) == 0, "Expected empty string\n"); LocalFree(buf); } ret = CryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, @@ -157,7 +157,7 @@ static void test_decodeSPCLink(void) link = (SPC_LINK *)buf; ok(link->dwLinkChoice == SPC_URL_LINK_CHOICE, "Expected SPC_URL_LINK_CHOICE, got %d\n", link->dwLinkChoice); - ok(!lstrcmpW(link->pwszUrl, url), "Unexpected URL\n"); + ok(!lstrcmpW(U(*link).pwszUrl, url), "Unexpected URL\n"); LocalFree(buf); } ret = CryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, @@ -169,7 +169,7 @@ static void test_decodeSPCLink(void) link = (SPC_LINK *)buf; ok(link->dwLinkChoice == SPC_FILE_LINK_CHOICE, "Expected SPC_FILE_LINK_CHOICE, got %d\n", link->dwLinkChoice); - ok(!lstrcmpW(link->pwszFile, nihongoURL), "Unexpected file\n"); + ok(!lstrcmpW(U(*link).pwszFile, nihongoURL), "Unexpected file\n"); LocalFree(buf); } ret = CryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, @@ -183,9 +183,9 @@ static void test_decodeSPCLink(void) link = (SPC_LINK *)buf; ok(link->dwLinkChoice == SPC_MONIKER_LINK_CHOICE, "Expected SPC_MONIKER_LINK_CHOICE, got %d\n", link->dwLinkChoice); - ok(!memcmp(&link->Moniker.ClassId, &emptyMoniker.ClassId, + ok(!memcmp(&U(*link).Moniker.ClassId, &emptyMoniker.ClassId, sizeof(emptyMoniker.ClassId)), "Unexpected value\n"); - ok(link->Moniker.SerializedData.cbData == 0, + ok(U(*link).Moniker.SerializedData.cbData == 0, "Expected no serialized data\n"); LocalFree(buf); } @@ -201,11 +201,11 @@ static void test_decodeSPCLink(void) ok(link->dwLinkChoice == SPC_MONIKER_LINK_CHOICE, "Expected SPC_MONIKER_LINK_CHOICE, got %d\n", link->dwLinkChoice); memset(&id, 0xea, sizeof(id)); - ok(!memcmp(&link->Moniker.ClassId, &id, sizeof(id)), + ok(!memcmp(&U(*link).Moniker.ClassId, &id, sizeof(id)), "Unexpected value\n"); - ok(link->Moniker.SerializedData.cbData == sizeof(data), - "Unexpected data size %d\n", link->Moniker.SerializedData.cbData); - ok(!memcmp(link->Moniker.SerializedData.pbData, data, sizeof(data)), + ok(U(*link).Moniker.SerializedData.cbData == sizeof(data), + "Unexpected data size %d\n", U(*link).Moniker.SerializedData.cbData); + ok(!memcmp(U(*link).Moniker.SerializedData.pbData, data, sizeof(data)), "Unexpected value\n"); LocalFree(buf); } @@ -311,7 +311,7 @@ static void test_encodeSPCPEImage(void) LocalFree(buf); } /* Finally, a non-empty file: */ - link.pwszFile = (LPWSTR)nihongoURL; + U(link).pwszFile = (LPWSTR)nihongoURL; ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT, &imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); @@ -374,7 +374,7 @@ static void test_decodeSPCPEImage(void) ok(imageData->pFile->dwLinkChoice == SPC_FILE_LINK_CHOICE, "Expected SPC_FILE_LINK_CHOICE, got %d\n", imageData->pFile->dwLinkChoice); - ok(!lstrcmpW(imageData->pFile->pwszFile, emptyString), + ok(!lstrcmpW(U(*imageData->pFile).pwszFile, emptyString), "Unexpected file\n"); } LocalFree(buf); @@ -397,7 +397,7 @@ static void test_decodeSPCPEImage(void) ok(imageData->pFile->dwLinkChoice == SPC_FILE_LINK_CHOICE, "Expected SPC_FILE_LINK_CHOICE, got %d\n", imageData->pFile->dwLinkChoice); - ok(!lstrcmpW(imageData->pFile->pwszFile, emptyString), + ok(!lstrcmpW(U(*imageData->pFile).pwszFile, emptyString), "Unexpected file\n"); } LocalFree(buf); @@ -420,7 +420,7 @@ static void test_decodeSPCPEImage(void) ok(imageData->pFile->dwLinkChoice == SPC_FILE_LINK_CHOICE, "Expected SPC_FILE_LINK_CHOICE, got %d\n", imageData->pFile->dwLinkChoice); - ok(!lstrcmpW(imageData->pFile->pwszFile, nihongoURL), + ok(!lstrcmpW(U(*imageData->pFile).pwszFile, nihongoURL), "Unexpected file\n"); } LocalFree(buf); diff --git a/dlls/wintrust/tests/softpub.c b/dlls/wintrust/tests/softpub.c index a8ce69e56fc..745cbeedf02 100644 --- a/dlls/wintrust/tests/softpub.c +++ b/dlls/wintrust/tests/softpub.c @@ -263,7 +263,7 @@ static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID) ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08x\n", data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]); - wintrust_data.pCert = &certInfo; + U(wintrust_data).pCert = &certInfo; wintrust_data.dwUnionChoice = WTD_CHOICE_CERT; ret = funcs->pfnObjectTrust(&data); ok(ret == S_OK, "Expected S_OK, got %08x\n", ret); @@ -274,14 +274,14 @@ static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID) CertFreeCertificateContext(certInfo.psCertContext); certInfo.psCertContext = NULL; wintrust_data.dwUnionChoice = WTD_CHOICE_FILE; - wintrust_data.pFile = NULL; + U(wintrust_data).pFile = NULL; ret = funcs->pfnObjectTrust(&data); ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret); ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08x\n", data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]); - wintrust_data.pFile = &fileInfo; + U(wintrust_data).pFile = &fileInfo; /* Crashes ret = funcs->pfnObjectTrust(&data); */ @@ -289,7 +289,7 @@ static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID) lstrcatW(notepadPath, notepad); fileInfo.pcwszFilePath = notepadPath; /* pfnObjectTrust now crashes unless both pPDSip and psPfns are set */ - data.pPDSip = &provDataSIP; + U(data).pPDSip = &provDataSIP; data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs; ret = funcs->pfnObjectTrust(&data); ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret); diff --git a/dlls/wldap32/wldap32_Fr.rc b/dlls/wldap32/wldap32_Fr.rc index d4b7458aebc..a7257544e7b 100644 --- a/dlls/wldap32/wldap32_Fr.rc +++ b/dlls/wldap32/wldap32_Fr.rc @@ -117,7 +117,7 @@ STRINGTABLE DISCARDABLE 92 "Opération non supportée par cette version du protocole LDAP" 93 "Le contrôle spécifié n'a pas été trouvé dans le message" 94 "Pas de résultat dans le message" - 95 "Plusde résultats retournés" + 95 "Plus de résultats retournés" 96 "Boucle lors du traitement des référants" 97 "Limite du nombre de référents dépassée" } diff --git a/include/Makefile.in b/include/Makefile.in index 660977b0b19..60b916ae86e 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -183,6 +183,7 @@ SRCDIR_INCLUDES = \ guiddef.h \ hlguids.h \ htmlhelp.h \ + i_cryptasn1tls.h \ icm.h \ icmpapi.h \ idispids.h \ diff --git a/include/i_cryptasn1tls.h b/include/i_cryptasn1tls.h new file mode 100644 index 00000000000..aee4adc7284 --- /dev/null +++ b/include/i_cryptasn1tls.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2007 Francois Gouget + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_I_CRYPTASN1TLS_H +#define __WINE_I_CRYPTASN1TLS_H + +typedef void *ASN1decoding_t; +typedef void *ASN1encoding_t; +typedef void *ASN1module_t; +typedef DWORD HCRYPTASN1MODULE; + + +#ifdef __cplusplus +extern "C" { +#endif + +ASN1decoding_t WINAPI I_CryptGetAsn1Decoder(HCRYPTASN1MODULE); +ASN1encoding_t WINAPI I_CryptGetAsn1Encoder(HCRYPTASN1MODULE); +BOOL WINAPI I_CryptInstallAsn1Module(ASN1module_t, DWORD, void*); +BOOL WINAPI I_CryptUninstallAsn1Module(HCRYPTASN1MODULE); + +#ifdef __cplusplus +} +#endif + +#endif /* __WINE_I_CRYPTASN1TLS_H */ diff --git a/include/objbase.h b/include/objbase.h index 4d94c0509cf..33fe4c9df89 100644 --- a/include/objbase.h +++ b/include/objbase.h @@ -329,6 +329,7 @@ HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree); void WINAPI CoFreeAllLibraries(void); void WINAPI CoFreeLibrary(HINSTANCE hLibrary); void WINAPI CoFreeUnusedLibraries(void); +void WINAPI CoFreeUnusedLibrariesEx(DWORD dwUnloadDelay, DWORD dwReserved); HRESULT WINAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv); HRESULT WINAPI CoCreateInstanceEx(REFCLSID rclsid, diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h index e98049cba5f..40d113dfd8d 100644 --- a/include/wine/wined3d_gl.h +++ b/include/wine/wined3d_gl.h @@ -2833,6 +2833,13 @@ typedef void (WINE_GLAPI * PGLFNGETTEXBUMPPARAMETERFVATIPROC) (GLenum, GLfloat * typedef int (WINE_GLAPI * PGLXFNGETVIDEOSYNCSGIPROC) (unsigned int *); typedef int (WINE_GLAPI * PGLXFNWAITVIDEOSYNCSGIPROC) (int, int, unsigned int *); +/* GL_SGIS_generate_mipmap */ +#ifndef GLX_SGIS_generate_mipmap +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 +#define GLX_SGIS_generate_mipmap +#endif + /* GL_VERSION_2_0 */ #ifndef GL_VERSION_2_0 #define GL_VERSION_2_0 1 @@ -3181,6 +3188,7 @@ typedef enum _GL_SupportedExt { APPLE_CLIENT_STORAGE, /* SGI */ SGI_VIDEO_SYNC, + SGIS_GENERATE_MIPMAP, /* WGL extensions */ WGL_ARB_PBUFFER, @@ -3346,9 +3354,9 @@ typedef enum _GL_SupportedExt { USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FARBPROC, glUniform2fARB); \ USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FARBPROC, glUniform3fARB); \ USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FARBPROC, glUniform4fARB); \ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IVARBPROC, glUniform1fvARB); \ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IVARBPROC, glUniform2fvARB); \ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM3IVARBPROC, glUniform3fvARB); \ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM1FVARBPROC, glUniform1fvARB); \ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FVARBPROC, glUniform2fvARB); \ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FVARBPROC, glUniform3fvARB); \ USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FVARBPROC, glUniform4fvARB); \ USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IVARBPROC, glUniform1ivARB); \ USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IVARBPROC, glUniform2ivARB); \ diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 8faa2970870..1d12706876f 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -2,6 +2,7 @@ * CMD - Wine-compatible command line interface - batch interface. * * Copyright (C) 1999 D A Pickles + * Copyright (C) 2007 J Edmeades * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,6 +20,9 @@ */ #include "wcmd.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(cmd); extern int echo_mode; extern WCHAR quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH]; @@ -131,7 +135,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, int called, WCHAR *startLabel, HAN /******************************************************************* * WCMD_parameter - extract a parameter from a command line. * - * Returns the 'n'th space-delimited parameter on the command line (zero-based). + * Returns the 'n'th delimited parameter on the command line (zero-based). * Parameter is in static storage overwritten on the next call. * Parameters in quotes (and brackets) are handled. * Also returns a pointer to the location of the parameter in the command line. @@ -147,7 +151,7 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where) { p = param; while (TRUE) { switch (*s) { - case ' ': + case ' ': /* Skip leading spaces */ s++; break; case '"': @@ -173,15 +177,20 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where) { default: /* Only return where if it is for the right parameter */ if (where != NULL && i==n) *where = s; - while ((*s != '\0') && (*s != ' ')) { + while ((*s != '\0') && (*s != ' ') && (*s != ',') && (*s != '=')) { *p++ = *s++; } - if (i == n) { + if (i == n && (p!=param)) { *p = '\0'; return param; } + /* Skip double delimiters, eg. dir a.a,,,,,b.b */ + if (p != param) { param[0] = '\0'; i++; + } else { + s++; /* Skip delimter */ + } p = param; } } @@ -301,7 +310,7 @@ void WCMD_splitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHA * Hence search forwards until find an invalid modifier, and then * backwards until find for variable or 0-9 */ -void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable) { +void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable, WCHAR *forValue, BOOL justFors) { #define NUMMODIFIERS 11 static const WCHAR validmodifiers[NUMMODIFIERS] = { @@ -324,10 +333,10 @@ void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable) { BOOL skipFileParsing = FALSE; BOOL doneModifier = FALSE; - /* Search forwards until find invalid WCHARacter modifier */ + /* Search forwards until find invalid character modifier */ while (!finished) { - /* Work on the previous WCHARacter */ + /* Work on the previous character */ if (lastModifier != NULL) { for (i=0; i= '0' || *lastModifier <= '9') && - (forVariable != NULL) && - (toupperW(*lastModifier) != toupperW(*forVariable))) { + while (lastModifier > firstModifier) { + WINE_TRACE("Looking backwards for parameter id: %s / %s\n", + wine_dbgstr_w(lastModifier), wine_dbgstr_w(forVariable)); - /* Its not... Step backwards until it matches or we get to the start */ - while (toupperW(*lastModifier) != toupperW(*forVariable) && - lastModifier > firstModifier) { + if (!justFors && context && (*lastModifier >= '0' || *lastModifier <= '9')) { + /* Its a valid parameter identifier - OK */ + break; + + } else if (forVariable && *lastModifier == *(forVariable+1)) { + /* Its a valid parameter identifier - OK */ + break; + + } else { lastModifier--; } - if (lastModifier == firstModifier) return; /* Invalid syntax */ } + if (lastModifier == firstModifier) return; /* Invalid syntax */ /* Extract the parameter to play with */ if ((*lastModifier >= '0' && *lastModifier <= '9')) { strcpyW(outputparam, WCMD_parameter (context -> command, *lastModifier-'0' + context -> shift_count[*lastModifier-'0'], NULL)); } else { - /* FIXME: Retrieve 'for' variable %c\n", *lastModifier); */ - /* Need to get 'for' loop variable into outputparam */ - return; + strcpyW(outputparam, forValue); } /* So now, firstModifier points to beginning of modifiers, lastModifier diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 1228206fc10..496ec86b45e 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -2,6 +2,7 @@ * CMD - Wine-compatible command line interface - built-in functions. * * Copyright (C) 1999 D A Pickles + * Copyright (C) 2007 J Edmeades * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -639,8 +640,6 @@ void WCMD_echo (const WCHAR *command) { * next cmdlist contains the DO cmd * following that is either brackets or && entries (as per if) * - * FIXME: We don't exhaustively check syntax. Any command which works in MessDOS - * will probably work here, but the reverse is not necessarily the case... */ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) { @@ -648,29 +647,89 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) { WIN32_FIND_DATA fd; HANDLE hff; int i; - const WCHAR inW[] = {'i', 'n', '\0'}; - const WCHAR doW[] = {'d', 'o', ' ','\0'}; + const WCHAR inW[] = {'i', 'n', ' ', '\0'}; + const WCHAR doW[] = {'d', 'o', ' ', '\0'}; CMD_LIST *setStart, *thisSet, *cmdStart, *cmdEnd; WCHAR variable[4]; WCHAR *firstCmd; int thisDepth; - /* Check: - the first line includes the % variable name as first parm - we have been provided with more parts to the command - and there is at least some set data - and IN as the one after that */ - if (lstrcmpiW (WCMD_parameter (p, 1, NULL), inW) - || (*cmdList) == NULL - || (*cmdList)->nextcommand == NULL - || (param1[0] != '%') - || (strlenW(param1) > 3)) { - WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR)); - return; + WCHAR *curPos = p; + BOOL expandDirs = FALSE; + BOOL useNumbers = FALSE; + BOOL doRecursive = FALSE; + BOOL doFileset = FALSE; + LONG numbers[3] = {0,0,0}; /* Defaults to 0 in native */ + int itemNum; + CMD_LIST *thisCmdStart; + + + /* Handle optional qualifiers (multiple are allowed) */ + while (*curPos && *curPos == '/') { + WINE_TRACE("Processing qualifier at %s\n", wine_dbgstr_w(curPos)); + curPos++; + switch (toupperW(*curPos)) { + case 'D': curPos++; expandDirs = TRUE; break; + case 'L': curPos++; useNumbers = TRUE; break; + + /* Recursive is special case - /R can have an optional path following it */ + /* filenamesets are another special case - /F can have an optional options following it */ + case 'R': + case 'F': + { + BOOL isRecursive = (*curPos == 'R'); + + if (isRecursive) doRecursive = TRUE; + else doFileset = TRUE; + + /* Skip whitespace */ + curPos++; + while (*curPos && *curPos==' ') curPos++; + + /* Next parm is either qualifier, path/options or variable - + only care about it if it is the path/options */ + if (*curPos && *curPos != '/' && *curPos != '%') { + if (isRecursive) WINE_FIXME("/R needs to handle supplied root\n"); + else WINE_FIXME("/F needs to handle options\n"); + } + break; + } + default: + WINE_FIXME("for qualifier '%c' unhandled\n", *curPos); + curPos++; + } + + /* Skip whitespace between qualifiers */ + while (*curPos && *curPos==' ') curPos++; + } + + /* Skip whitespace before variable */ + while (*curPos && *curPos==' ') curPos++; + + /* Ensure line continues with variable */ + if (!*curPos || *curPos != '%') { + WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR)); + return; + } + + /* Variable should follow */ + i = 0; + while (curPos[i] && curPos[i]!=' ') i++; + memcpy(&variable[0], curPos, i*sizeof(WCHAR)); + variable[i] = 0x00; + WINE_TRACE("Variable identified as %s\n", wine_dbgstr_w(variable)); + curPos = &curPos[i]; + + /* Skip whitespace before IN */ + while (*curPos && *curPos==' ') curPos++; + + /* Ensure line continues with IN */ + if (!*curPos || lstrcmpiW (curPos, inW)) { + WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR)); + return; } /* Save away where the set of data starts and the variable */ - strcpyW(variable, param1); thisDepth = (*cmdList)->bracketDepth; *cmdList = (*cmdList)->nextcommand; setStart = (*cmdList); @@ -702,6 +761,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) { cmdStart = *cmdList; cmdEnd = *cmdList; firstCmd = (*cmdList)->command + 3; /* Skip 'do ' */ + itemNum = 0; thisSet = setStart; /* Loop through all set entries */ @@ -711,37 +771,148 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) { /* Loop through all entries on the same line */ WCHAR *item; + WCHAR *itemStart; WINE_TRACE("Processing for set %p\n", thisSet); i = 0; - while (*(item = WCMD_parameter (thisSet->command, i, NULL))) { + while (*(item = WCMD_parameter (thisSet->command, i, &itemStart))) { /* * If the parameter within the set has a wildcard then search for matching files * otherwise do a literal substitution. */ static const WCHAR wildcards[] = {'*','?','\0'}; - CMD_LIST *thisCmdStart = cmdStart; + thisCmdStart = cmdStart; + + itemNum++; + WINE_TRACE("Processing for item %d '%s'\n", itemNum, wine_dbgstr_w(item)); + + if (!useNumbers && !doFileset) { + if (strpbrkW (item, wildcards)) { + hff = FindFirstFile (item, &fd); + if (hff != INVALID_HANDLE_VALUE) { + do { + BOOL isDirectory = FALSE; + + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) isDirectory = TRUE; + + /* Handle as files or dirs appropriately, but ignore . and .. */ + if (isDirectory == expandDirs && + (strcmpW(fd.cFileName, dotdotW) != 0) && + (strcmpW(fd.cFileName, dotW) != 0)) + { + thisCmdStart = cmdStart; + WINE_TRACE("Processing FOR filename %s\n", wine_dbgstr_w(fd.cFileName)); + WCMD_part_execute (&thisCmdStart, firstCmd, variable, + fd.cFileName, FALSE, TRUE); + } - WINE_TRACE("Processing for item '%s'\n", wine_dbgstr_w(item)); - if (strpbrkW (item, wildcards)) { - hff = FindFirstFile (item, &fd); - if (hff != INVALID_HANDLE_VALUE) { - do { - BOOL isDirectory = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); - if (!isDirectory) - { - thisCmdStart = cmdStart; - WINE_TRACE("Processing FOR filename %s\n", wine_dbgstr_w(fd.cFileName)); - WCMD_part_execute (&thisCmdStart, firstCmd, variable, - fd.cFileName, FALSE, TRUE); + } while (FindNextFile(hff, &fd) != 0); + FindClose (hff); } + } else { + WCMD_part_execute(&thisCmdStart, firstCmd, variable, item, FALSE, TRUE); + } - } while (FindNextFile(hff, &fd) != 0); - FindClose (hff); - } - } else { - WCMD_part_execute(&thisCmdStart, firstCmd, variable, item, FALSE, TRUE); + } else if (useNumbers) { + /* Convert the first 3 numbers to signed longs and save */ + if (itemNum <=3) numbers[itemNum-1] = atolW(item); + /* else ignore them! */ + + /* Filesets - either a list of files, or a command to run and parse the output */ + } else if (doFileset && *itemStart != '"') { + + HANDLE input; + WCHAR temp_file[MAX_PATH]; + + WINE_TRACE("Processing for filespec from item %d '%s'\n", itemNum, + wine_dbgstr_w(item)); + + /* If backquote or single quote, we need to launch that command + and parse the results - use a temporary file */ + if (*itemStart == '`' || *itemStart == '\'') { + + WCHAR temp_path[MAX_PATH], temp_cmd[MAXSTRING]; + static const WCHAR redirOut[] = {'>','%','s','\0'}; + static const WCHAR cmdW[] = {'C','M','D','\0'}; + + /* Remove trailing character */ + itemStart[strlenW(itemStart)-1] = 0x00; + + /* Get temp filename */ + GetTempPath (sizeof(temp_path)/sizeof(WCHAR), temp_path); + GetTempFileName (temp_path, cmdW, 0, temp_file); + + /* Execute program and redirect output */ + wsprintf (temp_cmd, redirOut, (itemStart+1), temp_file); + WCMD_execute (itemStart, temp_cmd, NULL, NULL, NULL); + + /* Open the file, read line by line and process */ + input = CreateFile (temp_file, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + } else { + + /* Open the file, read line by line and process */ + input = CreateFile (item, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + } + + /* Process the input file */ + if (input == INVALID_HANDLE_VALUE) { + WCMD_print_error (); + WCMD_output (WCMD_LoadMessage(WCMD_READFAIL), item); + errorlevel = 1; + return; /* FOR loop aborts at first failure here */ + + } else { + + WCHAR buffer[MAXSTRING] = {'\0'}; + WCHAR *where, *parm; + + while (WCMD_fgets (buffer, sizeof(buffer)/sizeof(WCHAR), input)) { + + /* Skip blank lines*/ + parm = WCMD_parameter (buffer, 0, &where); + WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm), + wine_dbgstr_w(buffer)); + + if (where) { + /* FIXME: The following should be moved into its own routine and + reused for the string literal parsing below */ + thisCmdStart = cmdStart; + WCMD_part_execute(&thisCmdStart, firstCmd, variable, parm, FALSE, TRUE); + cmdEnd = thisCmdStart; + } + + buffer[0] = 0x00; + + } + CloseHandle (input); + } + + /* Delete the temporary file */ + if (*itemStart == '`' || *itemStart == '\'') { + DeleteFile (temp_file); + } + + /* Filesets - A string literal */ + } else if (doFileset && *itemStart == '"') { + WCHAR buffer[MAXSTRING] = {'\0'}; + WCHAR *where, *parm; + + /* Skip blank lines, and re-extract parameter now string has quotes removed */ + strcpyW(buffer, item); + parm = WCMD_parameter (buffer, 0, &where); + WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm), + wine_dbgstr_w(buffer)); + + if (where) { + /* FIXME: The following should be moved into its own routine and + reused for the string literal parsing below */ + thisCmdStart = cmdStart; + WCMD_part_execute(&thisCmdStart, firstCmd, variable, parm, FALSE, TRUE); + cmdEnd = thisCmdStart; + } } WINE_TRACE("Post-command, cmdEnd = %p\n", cmdEnd); @@ -753,6 +924,26 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) { thisSet = thisSet->nextcommand; } + /* If /L is provided, now run the for loop */ + if (useNumbers) { + WCHAR thisNum[20]; + static const WCHAR fmt[] = {'%','d','\0'}; + + WINE_TRACE("FOR /L provided range from %d to %d step %d\n", + numbers[0], numbers[2], numbers[1]); + for (i=numbers[0]; + (numbers[1]<0)? i>numbers[2] : iredirects, variable, value, cmdList); free (command); } @@ -815,7 +1006,8 @@ void WCMD_part_execute(CMD_LIST **cmdList, WCHAR *firstcmd, WCHAR *variable, /* Execute any appended to the statement with &&'s */ if ((*cmdList)->isAmphersand) { if (processThese) { - WCMD_execute ((*cmdList)->command, variable, value, cmdList); + WCMD_execute ((*cmdList)->command, (*cmdList)->redirects, variable, + value, cmdList); } if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand; @@ -843,7 +1035,7 @@ void WCMD_part_execute(CMD_LIST **cmdList, WCHAR *firstcmd, WCHAR *variable, /* Skip leading whitespace between condition and the command */ while (*cmd && (*cmd==' ' || *cmd=='\t')) cmd++; if (*cmd) { - WCMD_execute (cmd, variable, value, cmdList); + WCMD_execute (cmd, (*cmdList)->redirects, variable, value, cmdList); } } if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand; @@ -857,40 +1049,6 @@ void WCMD_part_execute(CMD_LIST **cmdList, WCHAR *firstcmd, WCHAR *variable, return; } -/***************************************************************************** - * WCMD_Execute - * - * Execute a command after substituting variable text for the supplied parameter - */ - -void WCMD_execute (WCHAR *orig_cmd, WCHAR *param, WCHAR *subst, CMD_LIST **cmdList) { - - WCHAR *new_cmd, *p, *s, *dup; - int size; - - if (param) { - size = (strlenW (orig_cmd) + 1) * sizeof(WCHAR); - new_cmd = (WCHAR *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, size); - dup = s = WCMD_strdupW(orig_cmd); - - while ((p = strstrW (s, param))) { - *p = '\0'; - size += strlenW (subst) * sizeof(WCHAR); - new_cmd = (WCHAR *) LocalReAlloc ((HANDLE)new_cmd, size, 0); - strcatW (new_cmd, s); - strcatW (new_cmd, subst); - s = p + strlenW (param); - } - strcatW (new_cmd, s); - WCMD_process_command (new_cmd, cmdList); - free (dup); - LocalFree ((HANDLE)new_cmd); - } else { - WCMD_process_command (orig_cmd, cmdList); - } -} - - /************************************************************************** * WCMD_give_help * @@ -932,7 +1090,7 @@ void WCMD_goto (CMD_LIST **cmdList) { WCHAR string[MAX_PATH]; /* Do not process any more parts of a processed multipart or multilines command */ - *cmdList = NULL; + if (cmdList) *cmdList = NULL; if (param1[0] == 0x00) { WCMD_output (WCMD_LoadMessage(WCMD_NOARG)); @@ -1059,6 +1217,8 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) { else { strcpyW (condition, param1); } + WINE_TRACE("Condition: %s\n", wine_dbgstr_w(condition)); + if (!lstrcmpiW (condition, errlvlW)) { if (errorlevel >= atoiW(WCMD_parameter (p, 1+negate, NULL))) test = 1; WCMD_parameter (p, 2+negate, &command); diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c index 0de5bb8d2c9..483e496ab5d 100644 --- a/programs/cmd/directory.c +++ b/programs/cmd/directory.c @@ -2,6 +2,7 @@ * CMD - Wine-compatible command line interface - Directory functions. * * Copyright (C) 1999 D A Pickles + * Copyright (C) 2007 J Edmeades * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 0781fb6c8f4..d08ace21c35 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -2,6 +2,7 @@ * CMD - Wine-compatible command line interface. * * Copyright (C) 1999 D A Pickles + * Copyright (C) 2007 J Edmeades * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -32,6 +33,7 @@ typedef struct _CMD_LIST { WCHAR *command; /* Command string to execute */ + WCHAR *redirects; /* Redirects in place */ struct _CMD_LIST *nextcommand; /* Next command string to execute */ BOOL isAmphersand;/* Whether follows && */ int bracketDepth;/* How deep bracketing have we got to */ @@ -65,7 +67,6 @@ void WCMD_pause (void); void WCMD_pipe (CMD_LIST **command, WCHAR *var, WCHAR *val); void WCMD_popd (void); void WCMD_print_error (void); -void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList); void WCMD_pushd (WCHAR *); int WCMD_read_console (WCHAR *string, int str_len); void WCMD_remove_dir (WCHAR *command); @@ -92,7 +93,7 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where); WCHAR *WCMD_strtrim_leading_spaces (WCHAR *string); void WCMD_strtrim_trailing_spaces (WCHAR *string); void WCMD_opt_s_strip_quotes(WCHAR *cmd); -void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable); +void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable, WCHAR *forValue, BOOL justFors); BOOL WCMD_ask_confirm (WCHAR *message, BOOL showSureText, BOOL *optionAll); void WCMD_splitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext); @@ -104,7 +105,8 @@ BOOL WCMD_ReadFile(const HANDLE hIn, WCHAR *intoBuf, const DWORD maxChars, WCHAR *WCMD_ReadAndParseLine(WCHAR *initialcmd, CMD_LIST **output, HANDLE readFrom); CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket, WCHAR *var, WCHAR *val); void WCMD_free_commands(CMD_LIST *cmds); -void WCMD_execute (WCHAR *orig_command, WCHAR *parameter, WCHAR *substitution, CMD_LIST **cmdList); +void WCMD_execute (WCHAR *orig_command, WCHAR *redirects, WCHAR *parameter, + WCHAR *substitution, CMD_LIST **cmdList); /* Data structure to hold context when executing batch files */ diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 83185908e08..1d6c29e28cb 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -2,6 +2,7 @@ * CMD - Wine-compatible command line interface. * * Copyright (C) 1999 - 2001 D A Pickles + * Copyright (C) 2007 J Edmeades * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -95,7 +96,8 @@ static char *output_bufA = NULL; #define MAX_WRITECONSOLE_SIZE 65535 BOOL unicodePipes = FALSE; -static WCHAR *WCMD_expand_envvar(WCHAR *start); +static WCHAR *WCMD_expand_envvar(WCHAR *start, WCHAR *forvar, WCHAR *forVal); +static void WCMD_output_asis_len(const WCHAR *message, int len, HANDLE device); /***************************************************************************** * Main entry point. This is a console application so we have a main() not a @@ -456,6 +458,87 @@ int wmain (int argc, WCHAR *argvW[]) return 0; } +/***************************************************************************** + * Expand the command. Native expands lines from batch programs as they are + * read in and not again, except for 'for' variable substitution. + * eg. As evidence, "echo %1 && shift && echo %1" or "echo %%path%%" + */ +void handleExpansion(WCHAR *cmd, BOOL justFors, WCHAR *forVariable, WCHAR *forValue) { + + /* For commands in a context (batch program): */ + /* Expand environment variables in a batch file %{0-9} first */ + /* including support for any ~ modifiers */ + /* Additionally: */ + /* Expand the DATE, TIME, CD, RANDOM and ERRORLEVEL special */ + /* names allowing environment variable overrides */ + /* NOTE: To support the %PATH:xxx% syntax, also perform */ + /* manual expansion of environment variables here */ + + WCHAR *p = cmd; + WCHAR *s, *t; + int i; + + while ((p = strchrW(p, '%'))) { + + WINE_TRACE("Translate command:%s %d (at: %s)\n", + wine_dbgstr_w(cmd), justFors, wine_dbgstr_w(p)); + i = *(p+1) - '0'; + + /* Don't touch %% unless its in Batch */ + if (!justFors && *(p+1) == '%') { + if (context) { + s = WCMD_strdupW(p+1); + strcpyW (p, s); + free (s); + } + p+=1; + + /* Replace %~ modifications if in batch program */ + } else if (*(p+1) == '~') { + WCMD_HandleTildaModifiers(&p, forVariable, forValue, justFors); + p++; + + /* Replace use of %0...%9 if in batch program*/ + } else if (!justFors && context && (i >= 0) && (i <= 9)) { + s = WCMD_strdupW(p+2); + t = WCMD_parameter (context -> command, i + context -> shift_count[i], NULL); + strcpyW (p, t); + strcatW (p, s); + free (s); + + /* Replace use of %* if in batch program*/ + } else if (!justFors && context && *(p+1)=='*') { + WCHAR *startOfParms = NULL; + s = WCMD_strdupW(p+2); + t = WCMD_parameter (context -> command, 1, &startOfParms); + if (startOfParms != NULL) strcpyW (p, startOfParms); + else *p = 0x00; + strcatW (p, s); + free (s); + + } else if (forVariable && + (CompareString (LOCALE_USER_DEFAULT, + SORT_STRINGSORT, + p, + strlenW(forVariable), + forVariable, -1) == 2)) { + s = WCMD_strdupW(p + strlenW(forVariable)); + strcpyW(p, forValue); + strcatW(p, s); + free(s); + + } else if (!justFors) { + p = WCMD_expand_envvar(p, forVariable, forValue); + + /* In a FOR loop, see if this is the variable to replace */ + } else { /* Ignore %'s on second pass of batch program */ + p++; + } + } + + return; +} + /***************************************************************************** * Process one command. If the command is EXIT this routine does not return. @@ -463,16 +546,17 @@ int wmain (int argc, WCHAR *argvW[]) */ -void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList) +void WCMD_execute (WCHAR *command, WCHAR *redirects, + WCHAR *forVariable, WCHAR *forValue, + CMD_LIST **cmdList) { - WCHAR *cmd, *p, *s, *t, *redir; + WCHAR *cmd, *p, *redir; int status, i; DWORD count, creationDisposition; HANDLE h; WCHAR *whichcmd; SECURITY_ATTRIBUTES sa; WCHAR *new_cmd; - WCHAR *first_redir = NULL; HANDLE old_stdhandles[3] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; @@ -480,81 +564,24 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList) STD_OUTPUT_HANDLE, STD_ERROR_HANDLE}; + WINE_TRACE("command on entry:%s (%p), with '%s'='%s'\n", + wine_dbgstr_w(command), cmdList, + wine_dbgstr_w(forVariable), wine_dbgstr_w(forValue)); + /* Move copy of the command onto the heap so it can be expanded */ new_cmd = HeapAlloc( GetProcessHeap(), 0, MAXSTRING * sizeof(WCHAR)); strcpyW(new_cmd, command); - /* For commands in a context (batch program): */ - /* Expand environment variables in a batch file %{0-9} first */ - /* including support for any ~ modifiers */ - /* Additionally: */ - /* Expand the DATE, TIME, CD, RANDOM and ERRORLEVEL special */ - /* names allowing environment variable overrides */ - /* NOTE: To support the %PATH:xxx% syntax, also perform */ - /* manual expansion of environment variables here */ - - p = new_cmd; - while ((p = strchrW(p, '%'))) { - i = *(p+1) - '0'; - - /* Don't touch %% */ - if (*(p+1) == '%') { - p+=2; - - /* Replace %~ modifications if in batch program */ - } else if (context && *(p+1) == '~') { - WCMD_HandleTildaModifiers(&p, NULL); - p++; - - /* Replace use of %0...%9 if in batch program*/ - } else if (context && (i >= 0) && (i <= 9)) { - s = WCMD_strdupW(p+2); - t = WCMD_parameter (context -> command, i + context -> shift_count[i], NULL); - strcpyW (p, t); - strcatW (p, s); - free (s); - - /* Replace use of %* if in batch program*/ - } else if (context && *(p+1)=='*') { - WCHAR *startOfParms = NULL; - s = WCMD_strdupW(p+2); - t = WCMD_parameter (context -> command, 1, &startOfParms); - if (startOfParms != NULL) strcpyW (p, startOfParms); - else *p = 0x00; - strcatW (p, s); - free (s); - - } else { - p = WCMD_expand_envvar(p); - } - } + /* Expand variables in command line mode only (batch mode will + be expanded as the line is read in, except for for loops) */ + handleExpansion(new_cmd, (context != NULL), forVariable, forValue); cmd = new_cmd; - /* In a batch program, unknown variables are replace by nothing */ - /* so remove any remaining %var% */ - if (context) { - p = cmd; - while ((p = strchrW(p, '%'))) { - if (*(p+1) == '%') { - p+=2; - } else { - s = strchrW(p+1, '%'); - if (!s) { - *p=0x00; - } else { - t = WCMD_strdupW(s+1); - strcpyW(p, t); - free(t); - } - } - } - - /* Show prompt before batch line IF echo is on and in batch program */ - if (echo_mode && (cmd[0] != '@')) { - WCMD_show_prompt(); - WCMD_output_asis ( cmd); - WCMD_output_asis ( newline); - } + /* Show prompt before batch line IF echo is on and in batch program */ + if (context && echo_mode && (cmd[0] != '@')) { + WCMD_show_prompt(); + WCMD_output_asis ( cmd); + WCMD_output_asis ( newline); } /* @@ -588,8 +615,7 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList) * Redirect stdin, stdout and/or stderr if required. */ - if ((p = strchrW(cmd,'<')) != NULL) { - if (first_redir == NULL) first_redir = p; + if ((p = strchrW(redirects,'<')) != NULL) { h = CreateFile (WCMD_parameter (++p, 0, NULL), GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { @@ -602,15 +628,13 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList) } /* Scan the whole command looking for > and 2> */ - redir = cmd; + redir = redirects; while (redir != NULL && ((p = strchrW(redir,'>')) != NULL)) { int handle = 0; if (*(p-1)!='2') { - if (first_redir == NULL) first_redir = p; handle = 1; } else { - if (first_redir == NULL) first_redir = (p-1); handle = 2; } @@ -657,9 +681,6 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList) SetStdHandle (idx_stdhandles[handle], h); } - /* Terminate the command string at <, or first 2> or > */ - if (first_redir != NULL) *first_redir = '\0'; - /* * Strip leading whitespaces, and a '@' if supplied */ @@ -682,6 +703,8 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList) } p = WCMD_strtrim_leading_spaces (&whichcmd[count]); WCMD_parse (p, quals, param1, param2); + WINE_TRACE("param1: %s, param2: %s\n", wine_dbgstr_w(param1), wine_dbgstr_w(param2)); + switch (i) { case WCMD_ATTRIB: @@ -1239,9 +1262,12 @@ void WCMD_print_error (void) { error_code, GetLastError()); return; } - WCMD_output_asis (lpMsgBuf); + + WCMD_output_asis_len(lpMsgBuf, lstrlen(lpMsgBuf), + GetStdHandle(STD_ERROR_HANDLE)); LocalFree ((HLOCAL)lpMsgBuf); - WCMD_output_asis (newline); + WCMD_output_asis_len (newline, lstrlen(newline), + GetStdHandle(STD_ERROR_HANDLE)); return; } @@ -1287,11 +1313,15 @@ int p = 0; case '\0': return; default: - while ((*s != '\0') && (*s != ' ') && (*s != '\t')) { + while ((*s != '\0') && (*s != ' ') && (*s != '\t') + && (*s != '=') && (*s != ',') ) { if (p == 0) *p1++ = *s++; else if (p == 1) *p2++ = *s++; else s++; } + /* Skip concurrent parms */ + while ((*s == ' ') || (*s == '\t') || (*s == '=') || (*s == ',') ) s++; + if (p == 0) *p1 = '\0'; if (p == 1) *p2 = '\0'; p++; @@ -1306,7 +1336,7 @@ int p = 0; * and hence required WriteConsoleW to output it, however if file i/o is * redirected, it needs to be WriteFile'd using OEM (not ANSI) format */ -static void WCMD_output_asis_len(const WCHAR *message, int len) { +static void WCMD_output_asis_len(const WCHAR *message, int len, HANDLE device) { DWORD nOut= 0; DWORD res = 0; @@ -1315,8 +1345,7 @@ static void WCMD_output_asis_len(const WCHAR *message, int len) { if (!len) return; /* Try to write as unicode assuming it is to a console */ - res = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), - message, len, &nOut, NULL); + res = WriteConsoleW(device, message, len, &nOut, NULL); /* If writing to console fails, assume its file i/o so convert to OEM codepage and output */ @@ -1339,10 +1368,10 @@ static void WCMD_output_asis_len(const WCHAR *message, int len) { convertedChars = WideCharToMultiByte(GetConsoleOutputCP(), 0, message, len, output_bufA, MAX_WRITECONSOLE_SIZE, "?", &usedDefaultChar); - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), output_bufA, convertedChars, + WriteFile(device, output_bufA, convertedChars, &nOut, FALSE); } else { - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), message, len*sizeof(WCHAR), + WriteFile(device, message, len*sizeof(WCHAR), &nOut, FALSE); } } @@ -1368,7 +1397,7 @@ void WCMD_output (const WCHAR *format, ...) { string[ret] = '\0'; } va_end(ap); - WCMD_output_asis_len(string, ret); + WCMD_output_asis_len(string, ret, GetStdHandle(STD_OUTPUT_HANDLE)); } @@ -1419,19 +1448,22 @@ void WCMD_output_asis (const WCHAR *message) { ptr++; }; if (*ptr == '\n') ptr++; - WCMD_output_asis_len(message, (ptr) ? ptr - message : strlenW(message)); + WCMD_output_asis_len(message, (ptr) ? ptr - message : strlenW(message), + GetStdHandle(STD_OUTPUT_HANDLE)); if (ptr) { numChars = 0; if (++line_count >= max_height - 1) { line_count = 0; - WCMD_output_asis_len(pagedMessage, strlenW(pagedMessage)); + WCMD_output_asis_len(pagedMessage, strlenW(pagedMessage), + GetStdHandle(STD_OUTPUT_HANDLE)); WCMD_ReadFile (GetStdHandle(STD_INPUT_HANDLE), string, sizeof(string)/sizeof(WCHAR), &count, NULL); } } } while (((message = ptr) != NULL) && (*ptr)); } else { - WCMD_output_asis_len(message, lstrlen(message)); + WCMD_output_asis_len(message, lstrlen(message), + GetStdHandle(STD_OUTPUT_HANDLE)); } } @@ -1512,19 +1544,19 @@ void WCMD_pipe (CMD_LIST **cmdEntry, WCHAR *var, WCHAR *val) { p = strchrW(command, '|'); *p++ = '\0'; wsprintf (temp_cmd, redirOut, command, temp_file); - WCMD_execute (temp_cmd, var, val, cmdEntry); + WCMD_execute (temp_cmd, (*cmdEntry)->redirects, var, val, cmdEntry); command = p; while ((p = strchrW(command, '|'))) { *p++ = '\0'; GetTempFileName (temp_path, cmdW, 0, temp_file2); wsprintf (temp_cmd, redirBoth, command, temp_file, temp_file2); - WCMD_execute (temp_cmd, var, val, cmdEntry); + WCMD_execute (temp_cmd, (*cmdEntry)->redirects, var, val, cmdEntry); DeleteFile (temp_file); strcpyW (temp_file, temp_file2); command = p; } wsprintf (temp_cmd, redirIn, command, temp_file); - WCMD_execute (temp_cmd, var, val, cmdEntry); + WCMD_execute (temp_cmd, (*cmdEntry)->redirects, var, val, cmdEntry); DeleteFile (temp_file); } @@ -1533,7 +1565,7 @@ void WCMD_pipe (CMD_LIST **cmdEntry, WCHAR *var, WCHAR *val) { * * Expands environment variables, allowing for WCHARacter substitution */ -static WCHAR *WCMD_expand_envvar(WCHAR *start) { +static WCHAR *WCMD_expand_envvar(WCHAR *start, WCHAR *forVar, WCHAR *forVal) { WCHAR *endOfVar = NULL, *s; WCHAR *colonpos = NULL; WCHAR thisVar[MAXSTRING]; @@ -1551,20 +1583,38 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start) { static const WCHAR CdP[] = {'%','C','D','%','\0'}; static const WCHAR Random[] = {'R','A','N','D','O','M','\0'}; static const WCHAR RandomP[] = {'%','R','A','N','D','O','M','%','\0'}; + static const WCHAR Delims[] = {'%',' ',':','\0'}; + + WINE_TRACE("Expanding: %s (%s,%s)\n", wine_dbgstr_w(start), + wine_dbgstr_w(forVal), wine_dbgstr_w(forVar)); /* Find the end of the environment variable, and extract name */ - endOfVar = strchrW(start+1, '%'); - if (endOfVar == NULL) { + endOfVar = strpbrkW(start+1, Delims); + + if (endOfVar == NULL || *endOfVar==' ') { + /* In batch program, missing terminator for % and no following ':' just removes the '%' */ - s = WCMD_strdupW(start + 1); - strcpyW (start, s); - free(s); + if (context) { + s = WCMD_strdupW(start + 1); + strcpyW (start, s); + free(s); + return start; + } else { - /* FIXME: Some other special conditions here depending on whether - in batch, complex or not, and whether env var exists or not! */ - return start; + /* In command processing, just ignore it - allows command line + syntax like: for %i in (a.a) do echo %i */ + return start+1; + } } + + /* If ':' found, process remaining up until '%' (or stop at ':' if + a missing '%' */ + if (*endOfVar==':') { + WCHAR *endOfVar2 = strchrW(endOfVar+1, '%'); + if (endOfVar2 != NULL) endOfVar = endOfVar2; + } + memcpy(thisVar, start, ((endOfVar - start) + 1) * sizeof(WCHAR)); thisVar[(endOfVar - start)+1] = 0x00; colonpos = strchrW(thisVar+1, ':'); @@ -1627,6 +1677,16 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start) { wsprintf(thisVarContents, fmt, rand() % 32768); len = strlenW(thisVarContents); + /* Look for a matching 'for' variable */ + } else if (forVar && + (CompareString (LOCALE_USER_DEFAULT, + SORT_STRINGSORT, + thisVar, + (colonpos - thisVar) - 1, + forVar, -1) == 2)) { + strcpyW(thisVarContents, forVal); + len = strlenW(thisVarContents); + } else { len = ExpandEnvironmentStrings(thisVar, thisVarContents, @@ -1876,7 +1936,8 @@ void WCMD_DumpCommands(CMD_LIST *commands) { WCHAR buffer[MAXSTRING]; CMD_LIST *thisCmd = commands; const WCHAR fmt[] = {'%','p',' ','%','c',' ','%','2','.','2','d',' ', - '%','p',' ','%','s','\0'}; + '%','p',' ','%','s',' ','R','e','d','i','r',':', + '%','s','\0'}; WINE_TRACE("Parsed line:\n"); while (thisCmd != NULL) { @@ -1885,13 +1946,65 @@ void WCMD_DumpCommands(CMD_LIST *commands) { thisCmd->isAmphersand?'Y':'N', thisCmd->bracketDepth, thisCmd->nextcommand, - thisCmd->command); + thisCmd->command, + thisCmd->redirects); WINE_TRACE("%s\n", wine_dbgstr_w(buffer)); thisCmd = thisCmd->nextcommand; } } /*************************************************************************** + * WCMD_addCommand + * + * Adds a command to the current command list + */ +void WCMD_addCommand(WCHAR *command, int *commandLen, + WCHAR *redirs, int *redirLen, + WCHAR **copyTo, int **copyToLen, + BOOL isAmphersand, int curDepth, + CMD_LIST **lastEntry, CMD_LIST **output) { + + CMD_LIST *thisEntry = NULL; + + /* Allocate storage for command */ + thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST)); + + /* Copy in the command */ + if (command) { + thisEntry->command = HeapAlloc(GetProcessHeap(), 0, + (*commandLen+1) * sizeof(WCHAR)); + memcpy(thisEntry->command, command, *commandLen * sizeof(WCHAR)); + thisEntry->command[*commandLen] = 0x00; + + /* Copy in the redirects */ + thisEntry->redirects = HeapAlloc(GetProcessHeap(), 0, + (*redirLen+1) * sizeof(WCHAR)); + memcpy(thisEntry->redirects, redirs, *redirLen * sizeof(WCHAR)); + thisEntry->redirects[*redirLen] = 0x00; + + /* Reset the lengths */ + *commandLen = 0; + *redirLen = 0; + *copyToLen = commandLen; + *copyTo = command; + + } else { + thisEntry->command = NULL; + } + + /* Fill in other fields */ + thisEntry->nextcommand = NULL; + thisEntry->isAmphersand = isAmphersand; + thisEntry->bracketDepth = curDepth; + if (*lastEntry) { + (*lastEntry)->nextcommand = thisEntry; + } else { + *output = thisEntry; + } + *lastEntry = thisEntry; +} + +/*************************************************************************** * WCMD_ReadAndParseLine * * Either uses supplied input or @@ -1910,9 +2023,12 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF WCHAR *curPos; BOOL inQuotes = FALSE; WCHAR curString[MAXSTRING]; - int curLen = 0; + int curStringLen = 0; + WCHAR curRedirs[MAXSTRING]; + int curRedirsLen = 0; + WCHAR *curCopyTo; + int *curLen; int curDepth = 0; - CMD_LIST *thisEntry = NULL; CMD_LIST *lastEntry = NULL; BOOL isAmphersand = FALSE; static WCHAR *extraSpace = NULL; /* Deliberately never freed */ @@ -1930,6 +2046,7 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF BOOL lastWasDo = FALSE; BOOL lastWasIn = FALSE; BOOL lastWasElse = FALSE; + BOOL lastWasRedirect = TRUE; /* Allocate working space for a command read from keyboard, file etc */ if (!extraSpace) @@ -1952,8 +2069,15 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF WCMD_output_asis(newline); } - /* Start with an empty string */ - curLen = 0; + /* Replace env vars if in a batch context */ + if (context) handleExpansion(extraSpace, FALSE, NULL, NULL); + + /* Start with an empty string, copying to the command string */ + curStringLen = 0; + curRedirsLen = 0; + curCopyTo = curString; + curLen = &curStringLen; + lastWasRedirect = FALSE; /* Required for eg spaces between > and filename */ /* Parse every character on the line being processed */ while (*curPos != 0x00) { @@ -1961,12 +2085,12 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF WCHAR thisChar; /* Debugging AID: - WINE_TRACE("Looking at '%c' (len:%d, lws:%d, ows:%d)\n", *curPos, curLen, + WINE_TRACE("Looking at '%c' (len:%d, lws:%d, ows:%d)\n", *curPos, *curLen, lastWasWhiteSpace, onlyWhiteSpace); */ - /* Certain commands need special handling */ - if (curLen == 0) { + /* Certain commands need special handling */ + if (curStringLen == 0 && curCopyTo == curString) { const WCHAR forDO[] = {'d','o',' ','\0'}; /* If command starts with 'rem', ignore any &&, ( etc */ @@ -1994,8 +2118,8 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF inElse = TRUE; lastWasElse = TRUE; onlyWhiteSpace = TRUE; - memcpy(&curString[curLen], curPos, 5*sizeof(WCHAR)); - curLen+=5; + memcpy(&curCopyTo[*curLen], curPos, 5*sizeof(WCHAR)); + (*curLen)+=5; curPos+=5; continue; @@ -2008,12 +2132,12 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF WINE_TRACE("Found DO\n"); lastWasDo = TRUE; onlyWhiteSpace = TRUE; - memcpy(&curString[curLen], curPos, 3*sizeof(WCHAR)); - curLen+=3; + memcpy(&curCopyTo[*curLen], curPos, 3*sizeof(WCHAR)); + (*curLen)+=3; curPos+=3; continue; } - } else { + } else if (curCopyTo == curString) { /* Special handling for the 'FOR' command */ if (inFor && lastWasWhiteSpace) { @@ -2026,8 +2150,8 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF WINE_TRACE("Found IN\n"); lastWasIn = TRUE; onlyWhiteSpace = TRUE; - memcpy(&curString[curLen], curPos, 3*sizeof(WCHAR)); - curLen+=3; + memcpy(&curCopyTo[*curLen], curPos, 3*sizeof(WCHAR)); + (*curLen)+=3; curPos+=3; continue; } @@ -2044,17 +2168,84 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF switch (thisChar) { - case '\t':/* drop through - ignore whitespace at the start of a command */ - case ' ': if (curLen > 0) - curString[curLen++] = *curPos; + case '=': /* drop through - ignore token delimiters at the start of a command */ + case ',': /* drop through - ignore token delimiters at the start of a command */ + case '\t':/* drop through - ignore token delimiters at the start of a command */ + case ' ': + /* If a redirect in place, it ends here */ + if (!inQuotes && !lastWasRedirect) { + + /* If finishing off a redirect, add a whitespace delimiter */ + if (curCopyTo == curRedirs) { + curCopyTo[(*curLen)++] = ' '; + } + curCopyTo = curString; + curLen = &curStringLen; + } + if (*curLen > 0) { + curCopyTo[(*curLen)++] = *curPos; + } /* Remember just processed whitespace */ lastWasWhiteSpace = TRUE; break; + case '>': /* drop through - handle redirect chars the same */ + case '<': + /* Make a redirect start here */ + if (!inQuotes) { + curCopyTo = curRedirs; + curLen = &curRedirsLen; + lastWasRedirect = TRUE; + } + + /* See if 1>, 2> etc, in which case we have some patching up + to do */ + if (curPos != extraSpace && + *(curPos-1)>='1' && *(curPos-1)<='9') { + + curStringLen--; + curString[curStringLen] = 0x00; + curCopyTo[(*curLen)++] = *(curPos-1); + } + + curCopyTo[(*curLen)++] = *curPos; + break; + + case '|': /* Pipe character only if not || */ + if (!inQuotes && *(curPos++) == '|') { + + /* || is an alternative form of && but runs regardless */ + + /* If finishing off a redirect, add a whitespace delimiter */ + if (curCopyTo == curRedirs) { + curCopyTo[(*curLen)++] = ' '; + } + + /* If a redirect in place, it ends here */ + curCopyTo = curString; + curLen = &curStringLen; + curCopyTo[(*curLen)++] = *curPos; + lastWasRedirect = FALSE; + + } else if (inQuotes) { + curCopyTo[(*curLen)++] = *curPos; + lastWasRedirect = FALSE; + + } else { + /* Make a redirect start here */ + curCopyTo = curRedirs; + curLen = &curRedirsLen; + curCopyTo[(*curLen)++] = *curPos; + lastWasRedirect = TRUE; + } + break; + + case '"': inQuotes = !inQuotes; - curString[curLen++] = *curPos; + curCopyTo[(*curLen)++] = *curPos; + lastWasRedirect = FALSE; break; case '(': /* If a '(' is the first non whitespace in a command portion @@ -2063,18 +2254,19 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF WINE_TRACE("Found '(' conditions: curLen(%d), inQ(%d), onlyWS(%d)" ", for(%d, In:%d, Do:%d)" ", if(%d, else:%d, lwe:%d)\n", - curLen, inQuotes, + *curLen, inQuotes, onlyWhiteSpace, inFor, lastWasIn, lastWasDo, inIf, inElse, lastWasElse); + lastWasRedirect = FALSE; /* Ignore open brackets inside the for set */ - if (curLen == 0 && !inIn) { + if (*curLen == 0 && !inIn) { curDepth++; /* If in quotes, ignore brackets */ } else if (inQuotes) { - curString[curLen++] = *curPos; + curCopyTo[(*curLen)++] = *curPos; /* In a FOR loop, an unquoted '(' may occur straight after IN or DO @@ -2094,98 +2286,71 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF } /* Add the current command */ - thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST)); - thisEntry->command = HeapAlloc(GetProcessHeap(), 0, - (curLen+1) * sizeof(WCHAR)); - memcpy(thisEntry->command, curString, curLen * sizeof(WCHAR)); - thisEntry->command[curLen] = 0x00; - curLen = 0; - thisEntry->nextcommand = NULL; - thisEntry->isAmphersand = isAmphersand; - thisEntry->bracketDepth = curDepth; - if (lastEntry) { - lastEntry->nextcommand = thisEntry; - } else { - *output = thisEntry; - } - lastEntry = thisEntry; + WCMD_addCommand(curString, &curStringLen, + curRedirs, &curRedirsLen, + &curCopyTo, &curLen, + isAmphersand, curDepth, + &lastEntry, output); curDepth++; } else { - curString[curLen++] = *curPos; + curCopyTo[(*curLen)++] = *curPos; } break; case '&': if (!inQuotes && *(curPos+1) == '&') { curPos++; /* Skip other & */ + lastWasRedirect = FALSE; /* Add an entry to the command list */ - if (curLen > 0) { - thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST)); - thisEntry->command = HeapAlloc(GetProcessHeap(), 0, - (curLen+1) * sizeof(WCHAR)); - memcpy(thisEntry->command, curString, curLen * sizeof(WCHAR)); - thisEntry->command[curLen] = 0x00; - curLen = 0; - thisEntry->nextcommand = NULL; - thisEntry->isAmphersand = isAmphersand; - thisEntry->bracketDepth = curDepth; - if (lastEntry) { - lastEntry->nextcommand = thisEntry; - } else { - *output = thisEntry; - } - lastEntry = thisEntry; + if (curStringLen > 0) { + + /* Add the current command */ + WCMD_addCommand(curString, &curStringLen, + curRedirs, &curRedirsLen, + &curCopyTo, &curLen, + isAmphersand, curDepth, + &lastEntry, output); + } isAmphersand = TRUE; } else { - curString[curLen++] = *curPos; + curCopyTo[(*curLen)++] = *curPos; } break; case ')': if (!inQuotes && curDepth > 0) { + lastWasRedirect = FALSE; /* Add the current command if there is one */ - if (curLen) { - thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST)); - thisEntry->command = HeapAlloc(GetProcessHeap(), 0, - (curLen+1) * sizeof(WCHAR)); - memcpy(thisEntry->command, curString, curLen * sizeof(WCHAR)); - thisEntry->command[curLen] = 0x00; - curLen = 0; - thisEntry->nextcommand = NULL; - thisEntry->isAmphersand = isAmphersand; - thisEntry->bracketDepth = curDepth; - if (lastEntry) { - lastEntry->nextcommand = thisEntry; - } else { - *output = thisEntry; - } - lastEntry = thisEntry; + if (curStringLen) { + + /* Add the current command */ + WCMD_addCommand(curString, &curStringLen, + curRedirs, &curRedirsLen, + &curCopyTo, &curLen, + isAmphersand, curDepth, + &lastEntry, output); } /* Add an empty entry to the command list */ - thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST)); - thisEntry->command = NULL; - thisEntry->nextcommand = NULL; - thisEntry->isAmphersand = FALSE; - thisEntry->bracketDepth = curDepth; + isAmphersand = FALSE; + WCMD_addCommand(NULL, &curStringLen, + curRedirs, &curRedirsLen, + &curCopyTo, &curLen, + isAmphersand, curDepth, + &lastEntry, output); curDepth--; - if (lastEntry) { - lastEntry->nextcommand = thisEntry; - } else { - *output = thisEntry; - } - lastEntry = thisEntry; /* Leave inIn if necessary */ if (inIn) inIn = FALSE; } else { - curString[curLen++] = *curPos; + curCopyTo[(*curLen)++] = *curPos; } break; default: - curString[curLen++] = *curPos; + lastWasRedirect = FALSE; + curCopyTo[(*curLen)++] = *curPos; } curPos++; @@ -2201,24 +2366,14 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF } /* If we have reached the end, add this command into the list */ - if (*curPos == 0x00 && curLen > 0) { + if (*curPos == 0x00 && *curLen > 0) { /* Add an entry to the command list */ - thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST)); - thisEntry->command = HeapAlloc(GetProcessHeap(), 0, - (curLen+1) * sizeof(WCHAR)); - memcpy(thisEntry->command, curString, curLen * sizeof(WCHAR)); - thisEntry->command[curLen] = 0x00; - curLen = 0; - thisEntry->nextcommand = NULL; - thisEntry->isAmphersand = isAmphersand; - thisEntry->bracketDepth = curDepth; - if (lastEntry) { - lastEntry->nextcommand = thisEntry; - } else { - *output = thisEntry; - } - lastEntry = thisEntry; + WCMD_addCommand(curString, &curStringLen, + curRedirs, &curRedirsLen, + &curCopyTo, &curLen, + isAmphersand, curDepth, + &lastEntry, output); } /* If we have reached the end of the string, see if bracketing outstanding */ @@ -2234,6 +2389,7 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF if (WCMD_fgets(extraSpace, MAXSTRING, readFrom) == NULL) break; } curPos = extraSpace; + if (context) handleExpansion(extraSpace, FALSE, NULL, NULL); } } @@ -2276,10 +2432,10 @@ CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket, WINE_TRACE("Executing command: '%s'\n", wine_dbgstr_w(thisCmd->command)); - if (strchrW(thisCmd->command,'|') != NULL) { + if (strchrW(thisCmd->redirects,'|') != NULL) { WCMD_pipe (&thisCmd, var, val); } else { - WCMD_execute (thisCmd->command, var, val, &thisCmd); + WCMD_execute (thisCmd->command, thisCmd->redirects, var, val, &thisCmd); } } diff --git a/programs/wordpad/De.rc b/programs/wordpad/De.rc index 8eb6181cc5f..6478c64ebc9 100644 --- a/programs/wordpad/De.rc +++ b/programs/wordpad/De.rc @@ -27,6 +27,10 @@ BEGIN MENUITEM "&Speichern\tCtrl+S", ID_FILE_SAVE MENUITEM "Speichern &unter...", ID_FILE_SAVEAS MENUITEM SEPARATOR + MENUITEM "&Print . . .\tCtrl+P", ID_PRINT + MENUITEM "Print previe&w . . .", ID_PREVIEW + MENUITEM "Pag&e setup . . .", ID_PRINTSETUP + MENUITEM SEPARATOR MENUITEM "&Beenden", ID_FILE_EXIT END POPUP "&Bearbeiten" @@ -60,6 +64,8 @@ BEGIN MENUITEM "&Toolbar", ID_TOGGLE_TOOLBAR MENUITEM "&Formatbar", ID_TOGGLE_FORMATBAR MENUITEM "&Statusbar", ID_TOGGLE_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Options . . .", ID_VIEWPROPERTIES END POPUP "&Insert" BEGIN @@ -68,17 +74,30 @@ BEGIN POPUP "F&ormat" BEGIN MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT + MENUITEM "&Tabs . . ." ID_TABSTOPS POPUP "&Hintergrund" BEGIN MENUITEM "&System\tCtrl+1", ID_BACK_1 MENUITEM "&PostIt-Notiz\tCtrl+2", ID_BACK_2 END - POPUP "&Ausrichtung" - BEGIN - MENUITEM "&Links\tCtrl+L", ID_ALIGN_LEFT - MENUITEM "&Zentriert\tCtrl+E", ID_ALIGN_CENTER - MENUITEM "&Rechts\tCtrl+R", ID_ALIGN_RIGHT - END + END + POPUP "&Help" + BEGIN + MENUITEM "&About Wine Wordpad" ID_ABOUT + END +END + +IDM_POPUP MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "Aus&schneiden", ID_EDIT_CUT + MENUITEM "&Kopieren", ID_EDIT_COPY + MENUITEM "&Einfügen", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT END END @@ -104,6 +123,53 @@ BEGIN PUSHBUTTON "&Cancel",IDCANCEL,97,26,40,12 END +IDD_PARAFORMAT DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Paragraph format" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Indentation", 0, 10, 10, 120, 68 + LTEXT "Left", 0, 15, 22, 40, 13 + EDITTEXT IDC_PARA_LEFT, 55, 20, 60, 13 + LTEXT "Right", 0, 15, 40, 40, 13 + EDITTEXT IDC_PARA_RIGHT, 55, 38, 60, 13 + LTEXT "First line", 0, 15, 58, 40, 13 + EDITTEXT IDC_PARA_FIRST, 55, 56, 60, 13 + LTEXT "Alignment", 0, 15, 87, 40, 13 + COMBOBOX IDC_PARA_ALIGN, 55, 85, 60, 13, CBS_DROPDOWNLIST + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 +END + +IDD_TABSTOPS DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Tabs" +FONT 8, "MS SHell DLg" +BEGIN + GROUPBOX "Tab stops", 0, 10, 10, 120, 90 + COMBOBOX IDC_TABSTOPS, 20, 20, 100, 60, CBS_SIMPLE | CBS_SORT + DEFPUSHBUTTON "&Add", ID_TAB_ADD, 20, 80, 45, 15 + PUSHBUTTON "&Remove", ID_TAB_DEL, 72, 80, 45, 15 + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 + PUSHBUTTON "Remove al&l", ID_TAB_EMPTY, 137, 51, 50, 15 +END + +IDD_FORMATOPTS DIALOG DISCARDABLE 0, 0, 280, 110 +STYLE DS_SYSMODAL +Caption "" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Line wrapping", 0, 10, 10, 130, 85 + RADIOBUTTON "Wrap text by the &window border", IDC_PAGEFMT_WW, 18, 25, 117, 15 + RADIOBUTTON "Wrap text by the &margin", IDC_PAGEFMT_WM, 18, 45, 117, 15 + GROUPBOX "Toolbars", 0, 150, 10, 120, 85 + CHECKBOX "&Toolbar", IDC_PAGEFMT_TB, 160, 20, 80, 15 + CHECKBOX "&Formatbar", IDC_PAGEFMT_FB, 160, 38, 80, 15 + CHECKBOX "&Statusbar", IDC_PAGEFMT_SB, 160, 56, 80, 15 + LTEXT "", IDC_PAGEFMT_ID, 0,0,0,0 +END + STRINGTABLE DISCARDABLE BEGIN STRING_RICHTEXT_FILES_RTF, "Rich-Text-Format (*.rtf)" @@ -114,6 +180,13 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_ALIGN_LEFT, "Left" + STRING_ALIGN_RIGHT, "Right" + STRING_ALIGN_CENTER, "Center" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_NEWFILE_RICHTEXT, "Rich text document" STRING_NEWFILE_TXT, "Text document" STRING_NEWFILE_TXT_UNICODE, "Unicode text document" @@ -121,6 +194,31 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_PRINTER_FILES_PRN, "Printer files (*.PRN)" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_VIEWPROPS_TITLE, "Options" + STRING_VIEWPROPS_TEXT, "Text" + STRING_VIEWPROPS_RICHTEXT, "Rich text" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PREVIEW_PRINT, "Print" + STRING_PREVIEW_NEXTPAGE, "Next page" + STRING_PREVIEW_PREVPAGE, "Previous page" + STRING_PREVIEW_CLOSE, "Close" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_UNITS_CM, "cm" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_DEFAULT_FILENAME, "Document" STRING_PROMPT_SAVE_CHANGES, "Save changes to '%s'?" STRING_SEARCH_FINISHED, "Finished searching the document." @@ -128,4 +226,5 @@ BEGIN STRING_SAVE_LOSEFORMATTING, "You have chosen to save in plain text format, " \ "which will cause all formatting to be lost. " \ "Are you sure that you wish to do this?" + STRING_INVALID_NUMBER, "Invalid number format" END diff --git a/programs/wordpad/En.rc b/programs/wordpad/En.rc index fa258d0ebef..4eaa2da42a8 100644 --- a/programs/wordpad/En.rc +++ b/programs/wordpad/En.rc @@ -27,6 +27,10 @@ BEGIN MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE MENUITEM "Save &as . . .", ID_FILE_SAVEAS MENUITEM SEPARATOR + MENUITEM "&Print . . .\tCtrl+P", ID_PRINT + MENUITEM "Print previe&w . . .", ID_PREVIEW + MENUITEM "Pag&e setup . . .", ID_PRINTSETUP + MENUITEM SEPARATOR MENUITEM "E&xit", ID_FILE_EXIT END POPUP "&Edit" @@ -60,6 +64,8 @@ BEGIN MENUITEM "&Toolbar", ID_TOGGLE_TOOLBAR MENUITEM "&Formatbar", ID_TOGGLE_FORMATBAR MENUITEM "&Statusbar", ID_TOGGLE_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Options . . .", ID_VIEWPROPERTIES END POPUP "&Insert" BEGIN @@ -68,17 +74,30 @@ BEGIN POPUP "F&ormat" BEGIN MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT + MENUITEM "&Tabs . . ." ID_TABSTOPS POPUP "Backgroun&d" BEGIN MENUITEM "&System\tCtrl+1", ID_BACK_1 MENUITEM "&PostThat yellowish\tCtrl+2", ID_BACK_2 END - POPUP "&Alignment" - BEGIN - MENUITEM "&Left\tCtrl+L", ID_ALIGN_LEFT - MENUITEM "&Center\tCtrl+E", ID_ALIGN_CENTER - MENUITEM "&Right\tCtrl+R", ID_ALIGN_RIGHT - END + END + POPUP "&Help" + BEGIN + MENUITEM "&About Wine Wordpad" ID_ABOUT + END +END + +IDM_POPUP MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "Cu&t", ID_EDIT_CUT + MENUITEM "&Copy", ID_EDIT_COPY + MENUITEM "&Paste", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT END END @@ -104,6 +123,53 @@ BEGIN PUSHBUTTON "&Cancel",IDCANCEL,97,26,40,12 END +IDD_PARAFORMAT DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Paragraph format" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Indentation", 0, 10, 10, 120, 68 + LTEXT "Left", 0, 15, 22, 40, 13 + EDITTEXT IDC_PARA_LEFT, 55, 20, 60, 13 + LTEXT "Right", 0, 15, 40, 40, 13 + EDITTEXT IDC_PARA_RIGHT, 55, 38, 60, 13 + LTEXT "First line", 0, 15, 58, 40, 13 + EDITTEXT IDC_PARA_FIRST, 55, 56, 60, 13 + LTEXT "Alignment", 0, 15, 87, 40, 13 + COMBOBOX IDC_PARA_ALIGN, 55, 85, 60, 13, CBS_DROPDOWNLIST + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 +END + +IDD_TABSTOPS DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Tabs" +FONT 8, "MS SHell DLg" +BEGIN + GROUPBOX "Tab stops", 0, 10, 10, 120, 90 + COMBOBOX IDC_TABSTOPS, 20, 20, 100, 60, CBS_SIMPLE | CBS_SORT + DEFPUSHBUTTON "&Add", ID_TAB_ADD, 20, 80, 45, 15 + PUSHBUTTON "&Remove", ID_TAB_DEL, 72, 80, 45, 15 + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 + PUSHBUTTON "Remove al&l", ID_TAB_EMPTY, 137, 51, 50, 15 +END + +IDD_FORMATOPTS DIALOG DISCARDABLE 0, 0, 280, 110 +STYLE DS_SYSMODAL +Caption "" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Line wrapping", 0, 10, 10, 130, 85 + RADIOBUTTON "Wrap text by the &window border", IDC_PAGEFMT_WW, 18, 25, 117, 15 + RADIOBUTTON "Wrap text by the &margin", IDC_PAGEFMT_WM, 18, 45, 117, 15 + GROUPBOX "Toolbars", 0, 150, 10, 120, 85 + CHECKBOX "&Toolbar", IDC_PAGEFMT_TB, 160, 20, 80, 15 + CHECKBOX "&Formatbar", IDC_PAGEFMT_FB, 160, 38, 80, 15 + CHECKBOX "&Statusbar", IDC_PAGEFMT_SB, 160, 56, 80, 15 + LTEXT "", IDC_PAGEFMT_ID, 0,0,0,0 +END + STRINGTABLE DISCARDABLE BEGIN STRING_RICHTEXT_FILES_RTF, "Rich text format (*.rtf)" @@ -114,6 +180,13 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_ALIGN_LEFT, "Left" + STRING_ALIGN_RIGHT, "Right" + STRING_ALIGN_CENTER, "Center" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_NEWFILE_RICHTEXT, "Rich text document" STRING_NEWFILE_TXT, "Text document" STRING_NEWFILE_TXT_UNICODE, "Unicode text document" @@ -121,6 +194,31 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_PRINTER_FILES_PRN, "Printer files (*.PRN)" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_VIEWPROPS_TITLE, "Options" + STRING_VIEWPROPS_TEXT, "Text" + STRING_VIEWPROPS_RICHTEXT, "Rich text" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PREVIEW_PRINT, "Print" + STRING_PREVIEW_NEXTPAGE, "Next page" + STRING_PREVIEW_PREVPAGE, "Previous page" + STRING_PREVIEW_CLOSE, "Close" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_UNITS_CM, "cm" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_DEFAULT_FILENAME, "Document" STRING_PROMPT_SAVE_CHANGES, "Save changes to '%s'?" STRING_SEARCH_FINISHED, "Finished searching the document." @@ -128,4 +226,5 @@ BEGIN STRING_SAVE_LOSEFORMATTING, "You have chosen to save in plain text format, " \ "which will cause all formatting to be lost. " \ "Are you sure that you wish to do this?" + STRING_INVALID_NUMBER, "Invalid number format" END diff --git a/programs/wordpad/Fr.rc b/programs/wordpad/Fr.rc index 7113bcdb801..d69ce867168 100644 --- a/programs/wordpad/Fr.rc +++ b/programs/wordpad/Fr.rc @@ -27,6 +27,10 @@ BEGIN MENUITEM "&Enregistrer\tCtrl+S", ID_FILE_SAVE MENUITEM "Enregistrer &sous...", ID_FILE_SAVEAS MENUITEM SEPARATOR + MENUITEM "&Print . . .\tCtrl+P", ID_PRINT + MENUITEM "Print previe&w . . .", ID_PREVIEW + MENUITEM "Page setup . . .", ID_PRINTSETUP + MENUITEM SEPARATOR MENUITEM "&Quitter", ID_FILE_EXIT END POPUP "É&dition" @@ -60,6 +64,8 @@ BEGIN MENUITEM "&Barre d'outils", ID_TOGGLE_TOOLBAR MENUITEM "&Barre de format", ID_TOGGLE_FORMATBAR MENUITEM "&Barre d'état", ID_TOGGLE_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Options . . .", ID_VIEWPROPERTIES END POPUP "&Insert" BEGIN @@ -68,17 +74,30 @@ BEGIN POPUP "Forma&t" BEGIN MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT + MENUITEM "&Tabs . . ." ID_TABSTOPS POPUP "&Fond" BEGIN MENUITEM "&Système\tCtrl+1", ID_BACK_1 MENUITEM "&Jaunasse\tCtrl+2", ID_BACK_2 END - POPUP "&Alignement" - BEGIN - MENUITEM "Aligné à &gauche\tCtrl+L", ID_ALIGN_LEFT - MENUITEM "&Centré\tCtrl+E", ID_ALIGN_CENTER - MENUITEM "Aligné à &droite\tCtrl+R", ID_ALIGN_RIGHT - END + END + POPUP "&Help" + BEGIN + MENUITEM "&About Wine Wordpad" ID_ABOUT + END +END + +IDM_POPUP MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&Couper", ID_EDIT_CUT + MENUITEM "Co&pier", ID_EDIT_COPY + MENUITEM "C&oller", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT END END @@ -104,6 +123,53 @@ BEGIN PUSHBUTTON "&Cancel",IDCANCEL,97,26,40,12 END +IDD_PARAFORMAT DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Paragraph format" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Indentation", 0, 10, 10, 120, 68 + LTEXT "Left", 0, 15, 22, 40, 13 + EDITTEXT IDC_PARA_LEFT, 55, 20, 60, 13 + LTEXT "Right", 0, 15, 40, 40, 13 + EDITTEXT IDC_PARA_RIGHT, 55, 38, 60, 13 + LTEXT "First line", 0, 15, 58, 40, 13 + EDITTEXT IDC_PARA_FIRST, 55, 56, 60, 13 + LTEXT "Alignment", 0, 15, 87, 40, 13 + COMBOBOX IDC_PARA_ALIGN, 55, 85, 60, 13, CBS_DROPDOWNLIST + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 +END + +IDD_TABSTOPS DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Tabs" +FONT 8, "MS SHell DLg" +BEGIN + GROUPBOX "Tab stops", 0, 10, 10, 120, 90 + COMBOBOX IDC_TABSTOPS, 20, 20, 100, 60, CBS_SIMPLE | CBS_SORT + DEFPUSHBUTTON "&Add", ID_TAB_ADD, 20, 80, 45, 15 + PUSHBUTTON "&Remove", ID_TAB_DEL, 72, 80, 45, 15 + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 + PUSHBUTTON "Remove al&l", ID_TAB_EMPTY, 137, 51, 50, 15 +END + +IDD_FORMATOPTS DIALOG DISCARDABLE 0, 0, 280, 110 +STYLE DS_SYSMODAL +Caption "" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Line wrapping", 0, 10, 10, 130, 85 + RADIOBUTTON "Wrap text by the &window border", IDC_PAGEFMT_WW, 18, 25, 117, 15 + RADIOBUTTON "Wrap text by the &margin", IDC_PAGEFMT_WM, 18, 45, 117, 15 + GROUPBOX "Toolbars", 0, 150, 10, 120, 85 + CHECKBOX "&Toolbar", IDC_PAGEFMT_TB, 160, 20, 80, 15 + CHECKBOX "&Formatbar", IDC_PAGEFMT_FB, 160, 38, 80, 15 + CHECKBOX "&Statusbar", IDC_PAGEFMT_SB, 160, 56, 80, 15 + LTEXT "", IDC_PAGEFMT_ID, 0,0,0,0 +END + STRINGTABLE DISCARDABLE BEGIN STRING_RICHTEXT_FILES_RTF, "Rich text format (*.rtf)" @@ -114,6 +180,13 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_ALIGN_LEFT, "Left" + STRING_ALIGN_RIGHT, "Right" + STRING_ALIGN_CENTER, "Center" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_NEWFILE_RICHTEXT, "Rich text document" STRING_NEWFILE_TXT, "Text document" STRING_NEWFILE_TXT_UNICODE, "Unicode text document" @@ -121,6 +194,31 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_PRINTER_FILES_PRN, "Printer files (*.PRN)" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_VIEWPROPS_TITLE, "Options" + STRING_VIEWPROPS_TEXT, "Text" + STRING_VIEWPROPS_RICHTEXT, "Rich text" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PREVIEW_PRINT, "Print" + STRING_PREVIEW_NEXTPAGE, "Next page" + STRING_PREVIEW_PREVPAGE, "Previous page" + STRING_PREVIEW_CLOSE, "Close" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_UNITS_CM, "cm" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_DEFAULT_FILENAME, "Document" STRING_PROMPT_SAVE_CHANGES, "Save changes to '%s'?" STRING_SEARCH_FINISHED, "Finished searching the document." @@ -128,4 +226,5 @@ BEGIN STRING_SAVE_LOSEFORMATTING, "You have chosen to save in plain text format, " \ "which will cause all formatting to be lost. " \ "Are you sure that you wish to do this?" + STRING_INVALID_NUMBER, "Invalid number format" END diff --git a/programs/wordpad/Hu.rc b/programs/wordpad/Hu.rc index d74fed06d42..a6bdcccaa0b 100644 --- a/programs/wordpad/Hu.rc +++ b/programs/wordpad/Hu.rc @@ -27,6 +27,10 @@ BEGIN MENUITEM "M&entés\tCtrl+S", ID_FILE_SAVE MENUITEM "Mentés má&sként...", ID_FILE_SAVEAS MENUITEM SEPARATOR + MENUITEM "&Print . . .\tCtrl+P", ID_PRINT + MENUITEM "Print previe&w . . .", ID_PREVIEW + MENUITEM "Page setup . . .", ID_PRINTSETUP + MENUITEM SEPARATOR MENUITEM "&Kilépés", ID_FILE_EXIT END POPUP "Sz&erkesztés" @@ -60,6 +64,8 @@ BEGIN MENUITEM "&Toolbar", ID_TOGGLE_TOOLBAR MENUITEM "&Formatbar", ID_TOGGLE_FORMATBAR MENUITEM "&Statusbar", ID_TOGGLE_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Options . . .", ID_VIEWPROPERTIES END POPUP "&Insert" BEGIN @@ -68,17 +74,30 @@ BEGIN POPUP "F&ormátum" BEGIN MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT + MENUITEM "&Tabs . . ." ID_TABSTOPS POPUP "&Háttér" BEGIN MENUITEM "&Rendszer\tCtrl+1", ID_BACK_1 MENUITEM "&Sárgában kérem\tCtrl+2", ID_BACK_2 END - POPUP "&Igazítás" - BEGIN - MENUITEM "&Balra\tCtrl+L", ID_ALIGN_LEFT - MENUITEM "&Középre\tCtrl+E", ID_ALIGN_CENTER - MENUITEM "&Jobbra\tCtrl+R", ID_ALIGN_RIGHT - END + END + POPUP "&Help" + BEGIN + MENUITEM "&About Wine Wordpad" ID_ABOUT + END +END + +IDM_POPUP MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "Kiv&ágás\tCtrl+X", ID_EDIT_CUT + MENUITEM "Má&solás\tCtrl+C", ID_EDIT_COPY + MENUITEM "&Beillesztés\tCtrl+V", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT END END @@ -104,6 +123,53 @@ BEGIN PUSHBUTTON "&Cancel",IDCANCEL,97,26,40,12 END +IDD_PARAFORMAT DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Paragraph format" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Indentation", 0, 10, 10, 120, 68 + LTEXT "Left", 0, 15, 22, 40, 13 + EDITTEXT IDC_PARA_LEFT, 55, 20, 60, 13 + LTEXT "Right", 0, 15, 40, 40, 13 + EDITTEXT IDC_PARA_RIGHT, 55, 38, 60, 13 + LTEXT "First line", 0, 15, 58, 40, 13 + EDITTEXT IDC_PARA_FIRST, 55, 56, 60, 13 + LTEXT "Alignment", 0, 15, 87, 40, 13 + COMBOBOX IDC_PARA_ALIGN, 55, 85, 60, 13, CBS_DROPDOWNLIST + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 +END + +IDD_TABSTOPS DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Tabs" +FONT 8, "MS SHell DLg" +BEGIN + GROUPBOX "Tab stops", 0, 10, 10, 120, 90 + COMBOBOX IDC_TABSTOPS, 20, 20, 100, 60, CBS_SIMPLE | CBS_SORT + DEFPUSHBUTTON "&Add", ID_TAB_ADD, 20, 80, 45, 15 + PUSHBUTTON "&Remove", ID_TAB_DEL, 72, 80, 45, 15 + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 + PUSHBUTTON "Remove al&l", ID_TAB_EMPTY, 137, 51, 50, 15 +END + +IDD_FORMATOPTS DIALOG DISCARDABLE 0, 0, 280, 110 +STYLE DS_SYSMODAL +Caption "" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Line wrapping", 0, 10, 10, 130, 85 + RADIOBUTTON "Wrap text by the &window border", IDC_PAGEFMT_WW, 18, 25, 117, 15 + RADIOBUTTON "Wrap text by the &margin", IDC_PAGEFMT_WM, 18, 45, 117, 15 + GROUPBOX "Toolbars", 0, 150, 10, 120, 85 + CHECKBOX "&Toolbar", IDC_PAGEFMT_TB, 160, 20, 80, 15 + CHECKBOX "&Formatbar", IDC_PAGEFMT_FB, 160, 38, 80, 15 + CHECKBOX "&Statusbar", IDC_PAGEFMT_SB, 160, 56, 80, 15 + LTEXT "", IDC_PAGEFMT_ID, 0,0,0,0 +END + STRINGTABLE DISCARDABLE BEGIN STRING_RICHTEXT_FILES_RTF, "Rich text format (*.rtf)" @@ -114,6 +180,13 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_ALIGN_LEFT, "Left" + STRING_ALIGN_RIGHT, "Right" + STRING_ALIGN_CENTER, "Center" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_NEWFILE_RICHTEXT, "Rich text document" STRING_NEWFILE_TXT, "Text document" STRING_NEWFILE_TXT_UNICODE, "Unicode text document" @@ -121,6 +194,31 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_PRINTER_FILES_PRN, "Printer files (*.PRN)" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_VIEWPROPS_TITLE, "Options" + STRING_VIEWPROPS_TEXT, "Text" + STRING_VIEWPROPS_RICHTEXT, "Rich text" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PREVIEW_PRINT, "Print" + STRING_PREVIEW_NEXTPAGE, "Next page" + STRING_PREVIEW_PREVPAGE, "Previous page" + STRING_PREVIEW_CLOSE, "Close" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_UNITS_CM, "cm" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_DEFAULT_FILENAME, "Document" STRING_PROMPT_SAVE_CHANGES, "Save changes to '%s'?" STRING_SEARCH_FINISHED, "Finished searching the document." @@ -128,4 +226,5 @@ BEGIN STRING_SAVE_LOSEFORMATTING, "You have chosen to save in plain text format, " \ "which will cause all formatting to be lost. " \ "Are you sure that you wish to do this?" + STRING_INVALID_NUMBER, "Invalid number format" END diff --git a/programs/wordpad/Ko.rc b/programs/wordpad/Ko.rc index 5f82c82ee6c..6ee98fd13b3 100644 --- a/programs/wordpad/Ko.rc +++ b/programs/wordpad/Ko.rc @@ -28,6 +28,10 @@ BEGIN MENUITEM "ÀúÀå(&S)\tCtrl+S", ID_FILE_SAVE MENUITEM "´Ù¸¥ À̸§À¸·Î ÀúÀå(&A)...", ID_FILE_SAVEAS MENUITEM SEPARATOR + MENUITEM "&Print . . .\tCtrl+P", ID_PRINT + MENUITEM "Print previe&w . . .", ID_PREVIEW + MENUITEM "Pag&e setup . . .", ID_PRINTSETUP + MENUITEM SEPARATOR MENUITEM "³ª°¡±â(&X)", ID_FILE_EXIT END POPUP "ÆíÁý(&E)" @@ -61,6 +65,8 @@ BEGIN MENUITEM "µµ±¸¹Ù(&T)", ID_TOGGLE_TOOLBAR MENUITEM "Çü½Ä¹Ù(&F)", ID_TOGGLE_FORMATBAR MENUITEM "»óŹÙ(&S)", ID_TOGGLE_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Options . . .", ID_VIEWPROPERTIES END POPUP "Áý¾î³Ö±â(&I)" BEGIN @@ -69,17 +75,30 @@ BEGIN POPUP "Çü½Ä(&O)" BEGIN MENUITEM " °­Á¶ Á¡(&U)" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT + MENUITEM "&Tabs . . ." ID_TABSTOPS POPUP "¹è°æ(&B)" BEGIN MENUITEM "½Ã½ºÅÛ(&S)\tCtrl+1", ID_BACK_1 MENUITEM "³ë¶û»öÀ¸·Î(&P)\tCtrl+2", ID_BACK_2 END - POPUP "Á¤·Ä(&A)" - BEGIN - MENUITEM "¿ÞÂÊ(&L)\tCtrl+L", ID_ALIGN_LEFT - MENUITEM "°¡¿îµ¥(&C)\tCtrl+E", ID_ALIGN_CENTER - MENUITEM "¿À¸¥ÂÊ(&R)\tCtrl+R", ID_ALIGN_RIGHT - END + END + POPUP "&Help" + BEGIN + MENUITEM "&About Wine Wordpad" ID_ABOUT + END +END + +IDM_POPUP MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "À߶󳻱â(&T)", ID_EDIT_CUT + MENUITEM "º¹»ç(&C)", ID_EDIT_COPY + MENUITEM "ºÙ¿©³Ö±â(&P)", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT END END @@ -105,6 +124,53 @@ BEGIN PUSHBUTTON "Ãë¼Ò(&C)",IDCANCEL,97,26,40,12 END +IDD_PARAFORMAT DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Paragraph format" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Indentation", 0, 10, 10, 120, 68 + LTEXT "Left", 0, 15, 22, 40, 13 + EDITTEXT IDC_PARA_LEFT, 55, 20, 60, 13 + LTEXT "Right", 0, 15, 40, 40, 13 + EDITTEXT IDC_PARA_RIGHT, 55, 38, 60, 13 + LTEXT "First line", 0, 15, 58, 40, 13 + EDITTEXT IDC_PARA_FIRST, 55, 56, 60, 13 + LTEXT "Alignment", 0, 15, 87, 40, 13 + COMBOBOX IDC_PARA_ALIGN, 55, 85, 60, 13, CBS_DROPDOWNLIST + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 +END + +IDD_TABSTOPS DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Tabs" +FONT 8, "MS SHell DLg" +BEGIN + GROUPBOX "Tab stops", 0, 10, 10, 120, 90 + COMBOBOX IDC_TABSTOPS, 20, 20, 100, 60, CBS_SIMPLE | CBS_SORT + DEFPUSHBUTTON "&Add", ID_TAB_ADD, 20, 80, 45, 15 + PUSHBUTTON "&Remove", ID_TAB_DEL, 72, 80, 45, 15 + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 + PUSHBUTTON "Remove al&l", ID_TAB_EMPTY, 137, 51, 50, 15 +END + +IDD_FORMATOPTS DIALOG DISCARDABLE 0, 0, 280, 110 +STYLE DS_SYSMODAL +Caption "" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Line wrapping", 0, 10, 10, 130, 85 + RADIOBUTTON "Wrap text by the &window border", IDC_PAGEFMT_WW, 18, 25, 117, 15 + RADIOBUTTON "Wrap text by the &margin", IDC_PAGEFMT_WM, 18, 45, 117, 15 + GROUPBOX "Toolbars", 0, 150, 10, 120, 85 + CHECKBOX "&Toolbar", IDC_PAGEFMT_TB, 160, 20, 80, 15 + CHECKBOX "&Formatbar", IDC_PAGEFMT_FB, 160, 38, 80, 15 + CHECKBOX "&Statusbar", IDC_PAGEFMT_SB, 160, 56, 80, 15 + LTEXT "", IDC_PAGEFMT_ID, 0,0,0,0 +END + STRINGTABLE DISCARDABLE BEGIN STRING_RICHTEXT_FILES_RTF, "¸®Ä¡ ÅؽºÆ® ÆÄÀÏÇü½Ä (*.rtf)" @@ -115,6 +181,38 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_ALIGN_LEFT, "Left" + STRING_ALIGN_RIGHT, "Right" + STRING_ALIGN_CENTER, "Center" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PRINTER_FILES_PRN, "Printer files (*.PRN)" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_VIEWPROPS_TITLE, "Options" + STRING_VIEWPROPS_TEXT, "Text" + STRING_VIEWPROPS_RICHTEXT, "Rich text" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PREVIEW_PRINT, "Print" + STRING_PREVIEW_NEXTPAGE, "Next page" + STRING_PREVIEW_PREVPAGE, "Previous page" + STRING_PREVIEW_CLOSE, "Close" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_UNITS_CM, "cm" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_DEFAULT_FILENAME, "¹®¼­" STRING_PROMPT_SAVE_CHANGES, "'%s'ÀÇ ¹Ù²ï °ÍÀ» ÀúÀåÇÏ°Ú½À´Ï±î?" STRING_SEARCH_FINISHED, "¹®¼­¿¡¼­ ã±â ³¡." @@ -122,4 +220,5 @@ BEGIN STRING_SAVE_LOSEFORMATTING, "´ç½ÅÀº º¸Åë ÅؽºÆ® Çü½ÄÀ¸·Î ÀúÀåÇϱ⸦ ¼±ÅÃÇß½À´Ï´Ù, " \ "ÀÌ°ÍÀº Ư¼öÇÑ ²Ù¹ÒÀ» ¾ø¿¤ °ÍÀÔ´Ï´Ù. " \ "´ç½ÅÀº Á¤¸»·Î ÀúÀåÇϱ⸦ ¿øÇմϱî?" + STRING_INVALID_NUMBER, "Invalid number format" END diff --git a/programs/wordpad/Nl.rc b/programs/wordpad/Nl.rc index db0acbc82af..bc34cf3982b 100644 --- a/programs/wordpad/Nl.rc +++ b/programs/wordpad/Nl.rc @@ -27,6 +27,10 @@ BEGIN MENUITEM "O&pslaan\tCtrl+S", ID_FILE_SAVE MENUITEM "Ops&laan als...", ID_FILE_SAVEAS MENUITEM SEPARATOR + MENUITEM "&Print . . .\tCtrl+P", ID_PRINT + MENUITEM "Print previe&w . . .", ID_PREVIEW + MENUITEM "Pag&e setup . . .", ID_PRINTSETUP + MENUITEM SEPARATOR MENUITEM "&Afsluiten", ID_FILE_EXIT END POPUP "Be&werken" @@ -60,6 +64,8 @@ BEGIN MENUITEM "&Toolbar", ID_TOGGLE_TOOLBAR MENUITEM "&Formatbar", ID_TOGGLE_FORMATBAR MENUITEM "&Statusbar", ID_TOGGLE_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Options . . .", ID_VIEWPROPERTIES END POPUP "&Insert" BEGIN @@ -68,17 +74,30 @@ BEGIN POPUP "&Opmaak" BEGIN MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT + MENUITEM "&Tabs . . ." ID_TABSTOPS POPUP "&Achtergrond" BEGIN MENUITEM "&Systeem\tCtrl+1", ID_BACK_1 MENUITEM "&Geeltje\tCtrl+2", ID_BACK_2 END - POPUP "&Uitlijning" - BEGIN - MENUITEM "&Links\tCtrl+L", ID_ALIGN_LEFT - MENUITEM "&Gecentreerd\tCtrl+E", ID_ALIGN_CENTER - MENUITEM "&Rechts\tCtrl+R", ID_ALIGN_RIGHT - END + END + POPUP "&Help" + BEGIN + MENUITEM "&About Wine Wordpad" ID_ABOUT + END +END + +IDM_POPUP MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "K&nippen", ID_EDIT_CUT + MENUITEM "&Kopieren", ID_EDIT_COPY + MENUITEM "&Plakken", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT END END @@ -104,6 +123,53 @@ BEGIN PUSHBUTTON "&Cancel",IDCANCEL,97,26,40,12 END +IDD_PARAFORMAT DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Paragraph format" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Indentation", 0, 10, 10, 120, 68 + LTEXT "Left", 0, 15, 22, 40, 13 + EDITTEXT IDC_PARA_LEFT, 55, 20, 60, 13 + LTEXT "Right", 0, 15, 40, 40, 13 + EDITTEXT IDC_PARA_RIGHT, 55, 38, 60, 13 + LTEXT "First line", 0, 15, 58, 40, 13 + EDITTEXT IDC_PARA_FIRST, 55, 56, 60, 13 + LTEXT "Alignment", 0, 15, 87, 40, 13 + COMBOBOX IDC_PARA_ALIGN, 55, 85, 60, 13, CBS_DROPDOWNLIST + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 +END + +IDD_TABSTOPS DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Tabs" +FONT 8, "MS SHell DLg" +BEGIN + GROUPBOX "Tab stops", 0, 10, 10, 120, 90 + COMBOBOX IDC_TABSTOPS, 20, 20, 100, 60, CBS_SIMPLE | CBS_SORT + DEFPUSHBUTTON "&Add", ID_TAB_ADD, 20, 80, 45, 15 + PUSHBUTTON "&Remove", ID_TAB_DEL, 72, 80, 45, 15 + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 + PUSHBUTTON "Remove al&l", ID_TAB_EMPTY, 137, 51, 50, 15 +END + +IDD_FORMATOPTS DIALOG DISCARDABLE 0, 0, 280, 110 +STYLE DS_SYSMODAL +Caption "" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Line wrapping", 0, 10, 10, 130, 85 + RADIOBUTTON "Wrap text by the &window border", IDC_PAGEFMT_WW, 18, 25, 117, 15 + RADIOBUTTON "Wrap text by the &margin", IDC_PAGEFMT_WM, 18, 45, 117, 15 + GROUPBOX "Toolbars", 0, 150, 10, 120, 85 + CHECKBOX "&Toolbar", IDC_PAGEFMT_TB, 160, 20, 80, 15 + CHECKBOX "&Formatbar", IDC_PAGEFMT_FB, 160, 38, 80, 15 + CHECKBOX "&Statusbar", IDC_PAGEFMT_SB, 160, 56, 80, 15 + LTEXT "", IDC_PAGEFMT_ID, 0,0,0,0 +END + STRINGTABLE DISCARDABLE BEGIN STRING_RICHTEXT_FILES_RTF, "Rich text format (*.rtf)" @@ -114,6 +180,13 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_ALIGN_LEFT, "Left" + STRING_ALIGN_RIGHT, "Right" + STRING_ALIGN_CENTER, "Center" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_NEWFILE_RICHTEXT, "Rich text document" STRING_NEWFILE_TXT, "Text document" STRING_NEWFILE_TXT_UNICODE, "Unicode text document" @@ -121,6 +194,31 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_PRINTER_FILES_PRN, "Printer files (*.PRN)" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_VIEWPROPS_TITLE, "Options" + STRING_VIEWPROPS_TEXT, "Text" + STRING_VIEWPROPS_RICHTEXT, "Rich text" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PREVIEW_PRINT, "Print" + STRING_PREVIEW_NEXTPAGE, "Next page" + STRING_PREVIEW_PREVPAGE, "Previous page" + STRING_PREVIEW_CLOSE, "Close" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_UNITS_CM, "cm" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_DEFAULT_FILENAME, "Document" STRING_PROMPT_SAVE_CHANGES, "Save changes to '%s'?" STRING_SEARCH_FINISHED, "Finished searching the document." @@ -128,4 +226,5 @@ BEGIN STRING_SAVE_LOSEFORMATTING, "You have chosen to save in plain text format, " \ "which will cause all formatting to be lost. " \ "Are you sure that you wish to do this?" + STRING_INVALID_NUMBER, "Invalid number format" END diff --git a/programs/wordpad/No.rc b/programs/wordpad/No.rc index 0d56826e4f1..ad16960bc93 100644 --- a/programs/wordpad/No.rc +++ b/programs/wordpad/No.rc @@ -27,6 +27,10 @@ BEGIN MENUITEM "&Lagre\tCtrl+S", ID_FILE_SAVE MENUITEM "Lagre &som . . .", ID_FILE_SAVEAS MENUITEM SEPARATOR + MENUITEM "&Skriv ut . . .\tCtrl+P", ID_PRINT + MENUITEM "&Forhåndsvisning . . .", ID_PREVIEW + MENUITEM "&Utskriftformat . . .", ID_PRINTSETUP + MENUITEM SEPARATOR MENUITEM "&Avslutt", ID_FILE_EXIT END POPUP "R&ediger" @@ -60,6 +64,8 @@ BEGIN MENUITEM "Verk&tøylinje", ID_TOGGLE_TOOLBAR MENUITEM "&Formatlinje", ID_TOGGLE_FORMATBAR MENUITEM "&Statuslinje", ID_TOGGLE_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Alternativer . . .", ID_VIEWPROPERTIES END POPUP "Sett &inn" BEGIN @@ -68,17 +74,30 @@ BEGIN POPUP "F&ormat" BEGIN MENUITEM "&Punktmerking" ID_BULLET + MENUITEM "&Avsnitt . . ." ID_PARAFORMAT + MENUITEM "&Tabulatorer . . ." ID_TABSTOPS POPUP "&Bakgrunn" BEGIN MENUITEM "&System\tCtrl+1", ID_BACK_1 MENUITEM "Merkela&pp-gult\tCtrl+2", ID_BACK_2 END - POPUP "&Justering" - BEGIN - MENUITEM "&Venstrestilt\tCtrl+L", ID_ALIGN_LEFT - MENUITEM "&Midtstilt\tCtrl+E", ID_ALIGN_CENTER - MENUITEM "Høy&restilt\tCtrl+R", ID_ALIGN_RIGHT - END + END + POPUP "&Hjelp" + BEGIN + MENUITEM "&Om Wine Wordpad" ID_ABOUT + END +END + +IDM_POPUP MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "Klipp u&t" ID_EDIT_CUT + MENUITEM "&Kopier" ID_EDIT_COPY + MENUITEM "&Lim inn" ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "&Punktmerking" ID_BULLET + MENUITEM "&Avsnitt . . ." ID_PARAFORMAT END END @@ -104,6 +123,53 @@ BEGIN PUSHBUTTON "&Avbryt",IDCANCEL,97,26,40,12 END +IDD_PARAFORMAT DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Formater avsnitt" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Innrykk", 0, 10, 10, 120, 68 + LTEXT "Venstre", 0, 15, 22, 40, 13 + EDITTEXT IDC_PARA_LEFT, 55, 20, 60, 13 + LTEXT "Høyre", 0, 15, 40, 40, 13 + EDITTEXT IDC_PARA_RIGHT, 55, 38, 60, 13 + LTEXT "Første linje", 0, 15, 58, 40, 13 + EDITTEXT IDC_PARA_FIRST, 55, 56, 60, 13 + LTEXT "Justering", 0, 15, 87, 40, 13 + COMBOBOX IDC_PARA_ALIGN, 55, 85, 60, 13, CBS_DROPDOWNLIST + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Avbryt", IDCANCEL, 137, 33, 50, 15 +END + +IDD_TABSTOPS DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Tabulatorer" +FONT 8, "MS SHell DLg" +BEGIN + GROUPBOX "Tabulatorstopp", 0, 10, 10, 120, 90 + COMBOBOX IDC_TABSTOPS, 20, 20, 100, 60, CBS_SIMPLE | CBS_SORT + DEFPUSHBUTTON "&Legg til", ID_TAB_ADD, 20, 80, 45, 15 + PUSHBUTTON "&Fjern", ID_TAB_DEL, 72, 80, 45, 15 + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Avbryt", IDCANCEL, 137, 33, 50, 15 + PUSHBUTTON "Fjern all&e", ID_TAB_EMPTY, 137, 51, 50, 15 +END + +IDD_FORMATOPTS DIALOG DISCARDABLE 0, 0, 280, 110 +STYLE DS_SYSMODAL +Caption "" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Linjebryting", 0, 10, 10, 130, 85 + RADIOBUTTON "Bryt tekst etter v&indusbredden", IDC_PAGEFMT_WW, 18, 25, 117, 15 + RADIOBUTTON "Bryt tekst etter &margen", IDC_PAGEFMT_WM, 18, 45, 117, 15 + GROUPBOX "Verktøylinjer", 0, 150, 10, 120, 85 + CHECKBOX "&Verktøylinje", IDC_PAGEFMT_TB, 160, 20, 80, 15 + CHECKBOX "&Formatlinje", IDC_PAGEFMT_FB, 160, 38, 80, 15 + CHECKBOX "&Statuslinje", IDC_PAGEFMT_SB, 160, 56, 80, 15 + LTEXT "", IDC_PAGEFMT_ID, 0,0,0,0 +END + STRINGTABLE DISCARDABLE BEGIN STRING_RICHTEXT_FILES_RTF, "Rikt tekstformat (*.rtf)" @@ -121,6 +187,38 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_ALIGN_LEFT, "Venstrestilt" + STRING_ALIGN_RIGHT, "Høyrestilt" + STRING_ALIGN_CENTER, "Midtstilt" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PRINTER_FILES_PRN, "Skriverfiler (*.PRN)" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_VIEWPROPS_TITLE, "Alternativer" + STRING_VIEWPROPS_TEXT, "Tekst" + STRING_VIEWPROPS_RICHTEXT, "Rik tekst" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PREVIEW_PRINT, "Skriv ut" + STRING_PREVIEW_NEXTPAGE, "Neste side" + STRING_PREVIEW_PREVPAGE, "Forrige side" + STRING_PREVIEW_CLOSE, "Lukk" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_UNITS_CM, "cm" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_DEFAULT_FILENAME, "Dokument" STRING_PROMPT_SAVE_CHANGES, "Lagre endringer i «%s»?" STRING_SEARCH_FINISHED, "Ferdig med å søke i dokumentet." @@ -128,4 +226,5 @@ BEGIN STRING_SAVE_LOSEFORMATTING, "Du har valgt å lagre i rent tekstformat, noe som " \ "vil føre til at all formatering går tapt. Er du " \ "sikker på at du vil fortsette?" + STRING_INVALID_NUMBER, "Ugyldig tallformat" END diff --git a/programs/wordpad/Pl.rc b/programs/wordpad/Pl.rc index f6824833237..54e1d3aa0c8 100644 --- a/programs/wordpad/Pl.rc +++ b/programs/wordpad/Pl.rc @@ -28,6 +28,10 @@ BEGIN MENUITEM "&Zapisz\tCtrl+S", ID_FILE_SAVE MENUITEM "Z&apisz jako...", ID_FILE_SAVEAS MENUITEM SEPARATOR + MENUITEM "&Print . . .\tCtrl+P", ID_PRINT + MENUITEM "Print previe&w . . .", ID_PREVIEW + MENUITEM "Pag&e setup . . .", ID_PRINTSETUP + MENUITEM SEPARATOR MENUITEM "Za&koñcz", ID_FILE_EXIT END POPUP "&Edycja" @@ -61,6 +65,8 @@ BEGIN MENUITEM "&Toolbar", ID_TOGGLE_TOOLBAR MENUITEM "&Formatbar", ID_TOGGLE_FORMATBAR MENUITEM "&Statusbar", ID_TOGGLE_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Options . . .", ID_VIEWPROPERTIES END POPUP "&Insert" BEGIN @@ -69,17 +75,30 @@ BEGIN POPUP "F&ormat" BEGIN MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT + MENUITEM "Tab&s . . ." ID_TABSTOPS POPUP "&T³o" BEGIN MENUITEM "&System\tCtrl+1", ID_BACK_1 MENUITEM "&PostThat (¿ó³ty)\tCtrl+2", ID_BACK_2 END - POPUP "&Wyrównanie" - BEGIN - MENUITEM "Do &lewej\tCtrl+L", ID_ALIGN_LEFT - MENUITEM "&Wyœrodkowanie\tCtrl+E", ID_ALIGN_CENTER - MENUITEM "Do &Prawej\tCtrl+R", ID_ALIGN_RIGHT - END + END + POPUP "&Help" + BEGIN + MENUITEM "&About Wine Wordpad" ID_ABOUT + END +END + +IDM_POPUP MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "Wy&tnij", ID_EDIT_CUT + MENUITEM "&Kopiuj", ID_EDIT_COPY + MENUITEM "Wkl&ej", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT END END @@ -105,6 +124,53 @@ BEGIN PUSHBUTTON "&Cancel",IDCANCEL,97,26,40,12 END +IDD_PARAFORMAT DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Paragraph format" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Indentation", 0, 10, 10, 120, 68 + LTEXT "Left", 0, 15, 22, 40, 13 + EDITTEXT IDC_PARA_LEFT, 55, 20, 60, 13 + LTEXT "Right", 0, 15, 40, 40, 13 + EDITTEXT IDC_PARA_RIGHT, 55, 38, 60, 13 + LTEXT "First line", 0, 15, 58, 40, 13 + EDITTEXT IDC_PARA_FIRST, 55, 56, 60, 13 + LTEXT "Alignment", 0, 15, 87, 40, 13 + COMBOBOX IDC_PARA_ALIGN, 55, 85, 60, 13, CBS_DROPDOWNLIST + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 +END + +IDD_TABSTOPS DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Tabs" +FONT 8, "MS SHell DLg" +BEGIN + GROUPBOX "Tab stops", 0, 10, 10, 120, 90 + COMBOBOX IDC_TABSTOPS, 20, 20, 100, 60, CBS_SIMPLE | CBS_SORT + DEFPUSHBUTTON "&Add", ID_TAB_ADD, 20, 80, 45, 15 + PUSHBUTTON "&Remove", ID_TAB_DEL, 72, 80, 45, 15 + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 + PUSHBUTTON "Remove al&l", ID_TAB_EMPTY, 137, 51, 50, 15 +END + +IDD_FORMATOPTS DIALOG DISCARDABLE 0, 0, 280, 110 +STYLE DS_SYSMODAL +Caption "" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Line wrapping", 0, 10, 10, 130, 85 + RADIOBUTTON "Wrap text by the &window border", IDC_PAGEFMT_WW, 18, 25, 117, 15 + RADIOBUTTON "Wrap text by the &margin", IDC_PAGEFMT_WM, 18, 45, 117, 15 + GROUPBOX "Toolbars", 0, 150, 10, 120, 85 + CHECKBOX "&Toolbar", IDC_PAGEFMT_TB, 160, 20, 80, 15 + CHECKBOX "&Formatbar", IDC_PAGEFMT_FB, 160, 38, 80, 15 + CHECKBOX "&Statusbar", IDC_PAGEFMT_SB, 160, 56, 80, 15 + LTEXT "", IDC_PAGEFMT_ID, 0,0,0,0 +END + STRINGTABLE DISCARDABLE BEGIN STRING_RICHTEXT_FILES_RTF, "Tekst sformatowany - RTF (*.rtf)" @@ -115,6 +181,13 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_ALIGN_LEFT, "Left" + STRING_ALIGN_RIGHT, "Right" + STRING_ALIGN_CENTER, "Center" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_NEWFILE_RICHTEXT, "Rich text document" STRING_NEWFILE_TXT, "Text document" STRING_NEWFILE_TXT_UNICODE, "Unicode text document" @@ -122,6 +195,31 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_PRINTER_FILES_PRN, "Printer files (*.PRN)" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_VIEWPROPS_TITLE, "Options" + STRING_VIEWPROPS_TEXT, "Text" + STRING_VIEWPROPS_RICHTEXT, "Rich text" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PREVIEW_PRINT, "Print" + STRING_PREVIEW_NEXTPAGE, "Next page" + STRING_PREVIEW_PREVPAGE, "Previous page" + STRING_PREVIEW_CLOSE, "Close" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_UNITS_CM, "cm" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_DEFAULT_FILENAME, "Document" STRING_PROMPT_SAVE_CHANGES, "Save changes to '%s'?" STRING_SEARCH_FINISHED, "Finished searching the document." @@ -129,4 +227,5 @@ BEGIN STRING_SAVE_LOSEFORMATTING, "You have chosen to save in plain text format, " \ "which will cause all formatting to be lost. " \ "Are you sure that you wish to do this?" + STRING_INVALID_NUMBER, "Invalid number format" END diff --git a/programs/wordpad/Ru.rc b/programs/wordpad/Ru.rc index ecca77a348a..e6d6ae948aa 100644 --- a/programs/wordpad/Ru.rc +++ b/programs/wordpad/Ru.rc @@ -27,6 +27,10 @@ BEGIN MENUITEM "&Ñîõðàíèòü\tCtrl+S", ID_FILE_SAVE MENUITEM "Ñîõðàíèòü &êàê...", ID_FILE_SAVEAS MENUITEM SEPARATOR + MENUITEM "&Print . . .\tCtrl+P", ID_PRINT + MENUITEM "Print previe&w . . .", ID_PREVIEW + MENUITEM "Pag&e setup . . .", ID_PRINTSETUP + MENUITEM SEPARATOR MENUITEM "Â&ûõîä", ID_FILE_EXIT END POPUP "&Ïðàâêà" @@ -37,6 +41,7 @@ BEGIN MENUITEM SEPARATOR MENUITEM "&Âûðåçàòü\tCtrl+X", ID_EDIT_CUT MENUITEM "&Êîïèðîâàòü\tCtrl+C", ID_EDIT_COPY + MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE MENUITEM SEPARATOR MENUITEM "&Find . . .\tCrtl+F", ID_FIND MENUITEM "Find &next\tF3", ID_FIND_NEXT @@ -58,6 +63,8 @@ BEGIN MENUITEM "&Toolbar", ID_TOGGLE_TOOLBAR MENUITEM "&Formatbar", ID_TOGGLE_FORMATBAR MENUITEM "&Statusbar", ID_TOGGLE_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Options . . .", ID_VIEWPROPERTIES END POPUP "&Insert" BEGIN @@ -66,17 +73,30 @@ BEGIN POPUP "Ôîð&ìàò" BEGIN MENUITEM "B&ullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT + MENUITEM "&Tabs . . ." ID_TABSTOPS POPUP "&Ôîí" BEGIN MENUITEM "&Ñèñòåìíûé\tCtrl+1", ID_BACK_1 MENUITEM "&Æåëòîâàòûé PostThat\tCtrl+2", ID_BACK_2 END - POPUP "&Âûðàâíèâàíèå" - BEGIN - MENUITEM "Â&ëåâî\tCtrl+L", ID_ALIGN_LEFT - MENUITEM "Ïî &öåíòðó\tCtrl+E", ID_ALIGN_CENTER - MENUITEM "Â&ïðàâî\tCtrl+R", ID_ALIGN_RIGHT - END + END + POPUP "&Help" + BEGIN + MENUITEM "&About Wine Wordpad" ID_ABOUT + END +END + +IDM_POPUP MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&Âûðåçàòü\tCtrl+X", ID_EDIT_CUT + MENUITEM "&Êîïèðîâàòü\tCtrl+C", ID_EDIT_COPY + MENUITEM "&Paste", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT END END @@ -102,6 +122,53 @@ BEGIN PUSHBUTTON "&Cancel",IDCANCEL,97,26,40,12 END +IDD_PARAFORMAT DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Paragraph format" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Indentation", 0, 10, 10, 120, 68 + LTEXT "Left", 0, 15, 22, 40, 13 + EDITTEXT IDC_PARA_LEFT, 55, 20, 60, 13 + LTEXT "Right", 0, 15, 40, 40, 13 + EDITTEXT IDC_PARA_RIGHT, 55, 38, 60, 13 + LTEXT "First line", 0, 15, 58, 40, 13 + EDITTEXT IDC_PARA_FIRST, 55, 56, 60, 13 + LTEXT "Alignment", 0, 15, 87, 40, 13 + COMBOBOX IDC_PARA_ALIGN, 55, 85, 60, 13, CBS_DROPDOWNLIST + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 +END + +IDD_TABSTOPS DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Tabs" +FONT 8, "MS SHell DLg" +BEGIN + GROUPBOX "Tab stops", 0, 10, 10, 120, 90 + COMBOBOX IDC_TABSTOPS, 20, 20, 100, 60, CBS_SIMPLE | CBS_SORT + DEFPUSHBUTTON "&Add", ID_TAB_ADD, 20, 80, 45, 15 + PUSHBUTTON "&Remove", ID_TAB_DEL, 72, 80, 45, 15 + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 + PUSHBUTTON "Remove al&l", ID_TAB_EMPTY, 137, 51, 50, 15 +END + +IDD_FORMATOPTS DIALOG DISCARDABLE 0, 0, 280, 110 +STYLE DS_SYSMODAL +Caption "" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Line wrapping", 0, 10, 10, 130, 85 + RADIOBUTTON "Wrap text by the &window border", IDC_PAGEFMT_WW, 18, 25, 117, 15 + RADIOBUTTON "Wrap text by the &margin", IDC_PAGEFMT_WM, 18, 45, 117, 15 + GROUPBOX "Toolbars", 0, 150, 10, 120, 85 + CHECKBOX "&Toolbar", IDC_PAGEFMT_TB, 160, 20, 80, 15 + CHECKBOX "&Formatbar", IDC_PAGEFMT_FB, 160, 38, 80, 15 + CHECKBOX "&Statusbar", IDC_PAGEFMT_SB, 160, 56, 80, 15 + LTEXT "", IDC_PAGEFMT_ID, 0,0,0,0 +END + STRINGTABLE DISCARDABLE BEGIN STRING_RICHTEXT_FILES_RTF, "Rich text format (*.rtf)" @@ -112,6 +179,13 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_ALIGN_LEFT, "Left" + STRING_ALIGN_RIGHT, "Right" + STRING_ALIGN_CENTER, "Center" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_NEWFILE_RICHTEXT, "Rich text document" STRING_NEWFILE_TXT, "Text document" STRING_NEWFILE_TXT_UNICODE, "Unicode text document" @@ -119,6 +193,31 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_PRINTER_FILES_PRN, "Printer files (*.PRN)" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_VIEWPROPS_TITLE, "Options" + STRING_VIEWPROPS_TEXT, "Text" + STRING_VIEWPROPS_RICHTEXT, "Rich text" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PREVIEW_PRINT, "Print" + STRING_PREVIEW_NEXTPAGE, "Next page" + STRING_PREVIEW_PREVPAGE, "Previous page" + STRING_PREVIEW_CLOSE, "Close" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_UNITS_CM, "cm" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_DEFAULT_FILENAME, "Document" STRING_PROMPT_SAVE_CHANGES, "Save changes to '%s'?" STRING_SEARCH_FINISHED, "Finished searching the document." @@ -126,4 +225,5 @@ BEGIN STRING_SAVE_LOSEFORMATTING, "You have chosen to save in plain text format, " \ "which will cause all formatting to be lost. " \ "Are you sure that you wish to do this?" + STRING_INVALID_NUMBER, "Invalid number format" END diff --git a/programs/wordpad/Tr.rc b/programs/wordpad/Tr.rc index 54071658e6e..9a3013dd98a 100644 --- a/programs/wordpad/Tr.rc +++ b/programs/wordpad/Tr.rc @@ -28,6 +28,11 @@ BEGIN MENUITEM "&Aç...\tCtrl+O", ID_FILE_OPEN MENUITEM "&Kaydet\tCtrl+S", ID_FILE_SAVE MENUITEM "&Farklý Kaydet...", ID_FILE_SAVEAS + MENUITEM "Pag&e setup . . .", ID_PRINTSETUP + MENUITEM SEPARATOR + MENUITEM "&Print . . .\tCtrl+P", ID_PRINT + MENUITEM "Pag&e setup . . .", ID_PRINTSETUP + MENUITEM "Print previe&w . . .", ID_PREVIEW MENUITEM SEPARATOR MENUITEM "&Çýk", ID_FILE_EXIT END @@ -62,6 +67,8 @@ BEGIN MENUITEM "&Toolbar", ID_TOGGLE_TOOLBAR MENUITEM "&Formatbar", ID_TOGGLE_FORMATBAR MENUITEM "&Statusbar", ID_TOGGLE_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Options . . .", ID_VIEWPROPERTIES END POPUP "&Insert" BEGIN @@ -70,17 +77,30 @@ BEGIN POPUP "&Biçim" BEGIN MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT + MENUITEM "&Tabs . . ." ID_TABSTOPS POPUP "&Arkaplan" BEGIN MENUITEM "S&istem\tCtrl+1", ID_BACK_1 MENUITEM "&Sarýmtýrak\tCtrl+2", ID_BACK_2 END - POPUP "&Hizalama" - BEGIN - MENUITEM "S&ol\tCtrl+L", ID_ALIGN_LEFT - MENUITEM "O&rta\tCtrl+E", ID_ALIGN_CENTER - MENUITEM "S&að\tCtrl+R", ID_ALIGN_RIGHT - END + END + POPUP "&Help" + BEGIN + MENUITEM "&About Wine Wordpad" ID_ABOUT + END +END + +IDM_POPUP MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "Ke&s", ID_EDIT_CUT + MENUITEM "&Kopyala", ID_EDIT_COPY + MENUITEM "Ya&pýþtýr", ID_EDIT_PASTE + MENUITEM SEPARATOR + MENUITEM "&Bullet points" ID_BULLET + MENUITEM "&Paragraph . . ." ID_PARAFORMAT END END @@ -106,6 +126,53 @@ BEGIN PUSHBUTTON "&Cancel",IDCANCEL,97,26,40,12 END +IDD_PARAFORMAT DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Paragraph format" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Indentation", 0, 10, 10, 120, 68 + LTEXT "Left", 0, 15, 22, 40, 13 + EDITTEXT IDC_PARA_LEFT, 55, 20, 60, 13 + LTEXT "Right", 0, 15, 40, 40, 13 + EDITTEXT IDC_PARA_RIGHT, 55, 38, 60, 13 + LTEXT "First line", 0, 15, 58, 40, 13 + EDITTEXT IDC_PARA_FIRST, 55, 56, 60, 13 + LTEXT "Alignment", 0, 15, 87, 40, 13 + COMBOBOX IDC_PARA_ALIGN, 55, 85, 60, 13, CBS_DROPDOWNLIST + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 +END + +IDD_TABSTOPS DIALOG DISCARDABLE 30, 20, 200, 110 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +Caption "Tabs" +FONT 8, "MS SHell DLg" +BEGIN + GROUPBOX "Tab stops", 0, 10, 10, 120, 90 + COMBOBOX IDC_TABSTOPS, 20, 20, 100, 60, CBS_SIMPLE | CBS_SORT + DEFPUSHBUTTON "&Add", ID_TAB_ADD, 20, 80, 45, 15 + PUSHBUTTON "&Remove", ID_TAB_DEL, 72, 80, 45, 15 + PUSHBUTTON "&OK", IDOK, 137, 15, 50, 15 + PUSHBUTTON "&Cancel", IDCANCEL, 137, 33, 50, 15 + PUSHBUTTON "Remove al&l", ID_TAB_EMPTY, 137, 51, 50, 15 +END + +IDD_FORMATOPTS DIALOG DISCARDABLE 0, 0, 280, 110 +STYLE DS_SYSMODAL +Caption "" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Line wrapping", 0, 10, 10, 130, 85 + RADIOBUTTON "Wrap text by the &window border", IDC_PAGEFMT_WW, 18, 25, 117, 15 + RADIOBUTTON "Wrap text by the &margin", IDC_PAGEFMT_WM, 18, 45, 117, 15 + GROUPBOX "Toolbars", 0, 150, 10, 120, 85 + CHECKBOX "&Toolbar", IDC_PAGEFMT_TB, 160, 20, 80, 15 + CHECKBOX "&Formatbar", IDC_PAGEFMT_FB, 160, 38, 80, 15 + CHECKBOX "&Statusbar", IDC_PAGEFMT_SB, 160, 56, 80, 15 + LTEXT "", IDC_PAGEFMT_ID, 0,0,0,0 +END + STRINGTABLE DISCARDABLE BEGIN STRING_RICHTEXT_FILES_RTF, "Rich text format (*.rtf)" @@ -116,6 +183,13 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_ALIGN_LEFT, "Left" + STRING_ALIGN_RIGHT, "Right" + STRING_ALIGN_CENTER, "Center" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_NEWFILE_RICHTEXT, "Rich text document" STRING_NEWFILE_TXT, "Text document" STRING_NEWFILE_TXT_UNICODE, "Unicode text document" @@ -123,6 +197,31 @@ END STRINGTABLE DISCARDABLE BEGIN + STRING_PRINTER_FILES_PRN, "Printer files (*.PRN)" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_VIEWPROPS_TITLE, "Options" + STRING_VIEWPROPS_TEXT, "Text" + STRING_VIEWPROPS_RICHTEXT, "Rich text" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_PREVIEW_PRINT, "Print" + STRING_PREVIEW_NEXTPAGE, "Next page" + STRING_PREVIEW_PREVPAGE, "Previous page" + STRING_PREVIEW_CLOSE, "Close" +END + +STRINGTABLE DISCARDABLE +BEGIN + STRING_UNITS_CM, "cm" +END + +STRINGTABLE DISCARDABLE +BEGIN STRING_DEFAULT_FILENAME, "Document" STRING_PROMPT_SAVE_CHANGES, "Save changes to '%s'?" STRING_SEARCH_FINISHED, "Finished searching the document." @@ -130,4 +229,5 @@ BEGIN STRING_SAVE_LOSEFORMATTING, "You have chosen to save in plain text format, " \ "which will cause all formatting to be lost. " \ "Are you sure that you wish to do this?" + STRING_INVALID_NUMBER, "Invalid number format" END diff --git a/programs/wordpad/resource.h b/programs/wordpad/resource.h index ce2c1532ba3..9eaf97ea5e4 100644 --- a/programs/wordpad/resource.h +++ b/programs/wordpad/resource.h @@ -30,9 +30,14 @@ #define ID_PRINT 1010 #define ID_PREVIEW 1011 +#define ID_PRINTSETUP 1012 +#define ID_PRINT_QUICK 1013 -#define ID_FIND 1012 -#define ID_FIND_NEXT 1013 +#define ID_FIND 1014 +#define ID_FIND_NEXT 1015 + +#define ID_PREVIEW_NEXTPAGE 1016 +#define ID_PREVIEW_PREVPAGE 1017 #define ID_ALIGN_LEFT 1100 #define ID_ALIGN_CENTER 1101 @@ -65,15 +70,44 @@ #define ID_TOGGLE_FORMATBAR 1501 #define ID_TOGGLE_STATUSBAR 1502 -#define BANDID_TOOLBAR 0 -#define BANDID_FORMATBAR 1 +#define PREVIEW_BUTTONS 4 #define FILELIST_ENTRIES 4 #define FILELIST_ENTRY_LENGTH 33 +#define BANDID_TOOLBAR 2 +#define BANDID_FORMATBAR 3 +#define BANDID_RULER 0 +#define BANDID_STATUSBAR 1 + +#define BANDID_PREVIEW_BTN1 4 +#define BANDID_PREVIEW_BTN2 5 +#define BANDID_PREVIEW_BTN3 6 +#define BANDID_PREVIEW_BTN4 7 + +#define ID_WORDWRAP_NONE 0 +#define ID_WORDWRAP_WINDOW 1 +#define ID_WORDWRAP_MARGIN 2 + #define ID_NEWFILE_ABORT 100 +#define ID_TAB_ADD 100 +#define ID_TAB_DEL 101 +#define ID_TAB_EMPTY 102 + +#define IDC_PAGEFMT_TB 100 +#define IDC_PAGEFMT_FB 101 +#define IDC_PAGEFMT_SB 102 +#define IDC_PAGEFMT_WW 103 +#define IDC_PAGEFMT_WM 104 +#define IDC_PAGEFMT_ID 105 + #define ID_DATETIME 1600 +#define ID_PARAFORMAT 1601 +#define ID_TABSTOPS 1602 + +#define ID_ABOUT 1603 +#define ID_VIEWPROPERTIES 1604 #define IDC_STATUSBAR 2000 #define IDC_EDITOR 2001 @@ -83,9 +117,19 @@ #define IDC_COMBO 2005 #define IDC_DATETIME 2006 #define IDC_NEWFILE 2007 +#define IDC_PARA_LEFT 2008 +#define IDC_PARA_RIGHT 2009 +#define IDC_PARA_FIRST 2010 +#define IDC_PARA_ALIGN 2011 +#define IDC_TABSTOPS 2012 #define IDD_DATETIME 2100 #define IDD_NEWFILE 2101 +#define IDD_PARAFORMAT 2102 +#define IDD_TABSTOPS 2103 +#define IDD_FORMATOPTS 2104 + +#define IDM_POPUP 2200 #define IDB_TOOLBAR 100 #define IDB_FORMATBAR 101 @@ -101,8 +145,26 @@ #define STRING_NEWFILE_TXT 1405 #define STRING_NEWFILE_TXT_UNICODE 1406 +#define STRING_ALIGN_LEFT 1407 +#define STRING_ALIGN_RIGHT 1408 +#define STRING_ALIGN_CENTER 1409 + +#define STRING_PRINTER_FILES_PRN 1410 + +#define STRING_VIEWPROPS_TITLE 1411 +#define STRING_VIEWPROPS_TEXT 1412 +#define STRING_VIEWPROPS_RICHTEXT 1413 + +#define STRING_PREVIEW_PRINT 1414 +#define STRING_PREVIEW_NEXTPAGE 1415 +#define STRING_PREVIEW_PREVPAGE 1416 +#define STRING_PREVIEW_CLOSE 1417 + +#define STRING_UNITS_CM 1418 + #define STRING_DEFAULT_FILENAME 1700 #define STRING_PROMPT_SAVE_CHANGES 1701 #define STRING_SEARCH_FINISHED 1702 #define STRING_LOAD_RICHED_FAILED 1703 #define STRING_SAVE_LOSEFORMATTING 1704 +#define STRING_INVALID_NUMBER 1705 diff --git a/programs/wordpad/rsrc.rc b/programs/wordpad/rsrc.rc index d53e6f48376..ee192523f58 100644 --- a/programs/wordpad/rsrc.rc +++ b/programs/wordpad/rsrc.rc @@ -41,6 +41,7 @@ BEGIN "N", ID_FILE_NEW, VIRTKEY, CONTROL "O", ID_FILE_OPEN, VIRTKEY, CONTROL "S", ID_FILE_SAVE, VIRTKEY, CONTROL + "P", ID_PRINT, VIRTKEY, CONTROL END /* BINRES toolbar.bmp */ diff --git a/programs/wordpad/wordpad.c b/programs/wordpad/wordpad.c index a8c39d6988d..c4ad8717b8a 100644 --- a/programs/wordpad/wordpad.c +++ b/programs/wordpad/wordpad.c @@ -33,6 +33,9 @@ #include #include #include +#include +#include +#include #include "resource.h" @@ -47,20 +50,28 @@ static const WCHAR wszAppTitle[] = {'W','i','n','e',' ','W','o','r','d','p','a', static const WCHAR key_recentfiles[] = {'R','e','c','e','n','t',' ','f','i','l','e', ' ','l','i','s','t',0}; static const WCHAR key_options[] = {'O','p','t','i','o','n','s',0}; +static const WCHAR key_rtf[] = {'R','T','F',0}; +static const WCHAR key_text[] = {'T','e','x','t',0}; static const WCHAR var_file[] = {'F','i','l','e','%','d',0}; static const WCHAR var_framerect[] = {'F','r','a','m','e','R','e','c','t',0}; - +static const WCHAR var_barstate0[] = {'B','a','r','S','t','a','t','e','0',0}; +static const WCHAR var_pagemargin[] = {'P','a','g','e','M','a','r','g','i','n',0}; static HWND hMainWnd; static HWND hEditorWnd; static HWND hFindWnd; +static HMENU hPopupMenu; static UINT ID_FINDMSGSTRING; static WCHAR wszFilter[MAX_STRING_LEN*4+6*3+5]; static WCHAR wszDefaultFileName[MAX_STRING_LEN]; static WCHAR wszSaveChanges[MAX_STRING_LEN]; +static WCHAR wszPrintFilter[MAX_STRING_LEN*2+6+4+1]; +static WCHAR units_cmW[MAX_STRING_LEN]; + +static char units_cmA[MAX_STRING_LEN]; static LRESULT OnSize( HWND hWnd, WPARAM wParam, LPARAM lParam ); @@ -71,6 +82,7 @@ static void DoLoadStrings(void) static const WCHAR files_rtf[] = {'*','.','r','t','f','\0'}; static const WCHAR files_txt[] = {'*','.','t','x','t','\0'}; static const WCHAR files_all[] = {'*','.','*','\0'}; + static const WCHAR files_prn[] = {'*','.','P','R','N',0}; HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hMainWnd, GWLP_HINSTANCE); LoadStringW(hInstance, STRING_RICHTEXT_FILES_RTF, p, MAX_STRING_LEN); @@ -91,11 +103,25 @@ static void DoLoadStrings(void) p += lstrlenW(p) + 1; *p = '\0'; + p = wszPrintFilter; + LoadStringW(hInstance, STRING_PRINTER_FILES_PRN, p, MAX_STRING_LEN); + p += lstrlenW(p) + 1; + lstrcpyW(p, files_prn); + p += lstrlenW(p) + 1; + LoadStringW(hInstance, STRING_ALL_FILES, p, MAX_STRING_LEN); + p += lstrlenW(p) + 1; + lstrcpyW(p, files_all); + p += lstrlenW(p) + 1; + *p = 0; + p = wszDefaultFileName; LoadStringW(hInstance, STRING_DEFAULT_FILENAME, p, MAX_STRING_LEN); p = wszSaveChanges; LoadStringW(hInstance, STRING_PROMPT_SAVE_CHANGES, p, MAX_STRING_LEN); + + LoadStringA(hInstance, STRING_UNITS_CM, units_cmA, MAX_STRING_LEN); + LoadStringW(hInstance, STRING_UNITS_CM, units_cmW, MAX_STRING_LEN); } static void AddButton(HWND hwndToolBar, int nImage, int nCommand) @@ -112,6 +138,36 @@ static void AddButton(HWND hwndToolBar, int nImage, int nCommand) SendMessageW(hwndToolBar, TB_ADDBUTTONSW, 1, (LPARAM)&button); } +static void AddTextButton(HWND hWnd, int string, int command, int id) +{ + REBARBANDINFOW rb; + HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hMainWnd, GWLP_HINSTANCE); + static const WCHAR button[] = {'B','U','T','T','O','N',0}; + WCHAR text[MAX_STRING_LEN]; + HWND hButton; + RECT rc; + + LoadStringW(hInstance, string, text, MAX_STRING_LEN); + hButton = CreateWindowW(button, text, + WS_VISIBLE | WS_CHILD, 5, 5, 100, 15, + hMainWnd, (HMENU)command, hInstance, NULL); + + rb.cbSize = sizeof(rb); + rb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_ID; + rb.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT; + rb.hwndChild = hButton; + rb.cyChild = rb.cyMinChild = 22; + rb.cx = rb.cxMinChild = 90; + rb.cxIdeal = 100; + rb.wID = id; + + rc.bottom = 22; + rc.right = 90; + + SendMessageW(hWnd, RB_INSERTBAND, -1, (LPARAM)&rb); + SetWindowPos(hButton, 0, 0, 0, 90, 22, SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER); +} + static void AddSeparator(HWND hwndToolBar) { TBBUTTON button; @@ -244,7 +300,9 @@ static LRESULT registry_get_handle(HKEY *hKey, LPDWORD action, LPCWSTR subKey) return ret; } -static void registry_set_winrect(void) +static RECT margins; + +static void registry_set_options(void) { HKEY hKey; DWORD action; @@ -256,6 +314,8 @@ static void registry_set_winrect(void) GetWindowRect(hMainWnd, &rc); RegSetValueExW(hKey, var_framerect, 0, REG_BINARY, (LPBYTE)&rc, sizeof(RECT)); + + RegSetValueExW(hKey, var_pagemargin, 0, REG_BINARY, (LPBYTE)&margins, sizeof(RECT)); } } @@ -471,6 +531,45 @@ static void registry_set_filelist(LPCWSTR newFile) registry_read_filelist(hMainWnd); } +static BOOL validate_endptr(LPCSTR endptr, BOOL units) +{ + if(!endptr || !*endptr) + return TRUE; + + while(*endptr == ' ') + endptr++; + + if(!units) + return *endptr != '\0'; + + /* FIXME: Allow other units and convert between them */ + if(!lstrcmpA(endptr, units_cmA)) + endptr += 2; + + return *endptr != '\0'; +} + +static BOOL number_from_string(LPCWSTR string, float *num, BOOL units) +{ + double ret; + char buffer[MAX_STRING_LEN]; + char *endptr = buffer; + + WideCharToMultiByte(CP_ACP, 0, string, -1, buffer, MAX_STRING_LEN, NULL, NULL); + *num = 0; + errno = 0; + ret = strtod(buffer, &endptr); + + if((ret == 0 && errno != 0) || endptr == buffer || validate_endptr(endptr, units)) + { + return FALSE; + } else + { + *num = (float)ret; + return TRUE; + } +} + static void clear_formatting(void) { PARAFORMAT2 pf; @@ -481,6 +580,11 @@ static void clear_formatting(void) SendMessageW(hEditorWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf); } +static int reg_formatindex(WPARAM format) +{ + return (format & SF_TEXT) ? 1 : 0; +} + static int fileformat_number(WPARAM format) { int number = 0; @@ -502,9 +606,204 @@ static WPARAM fileformat_flags(int format) return flags[format]; } +static void set_default_font(void) +{ + static const WCHAR richTextFont[] = {'T','i','m','e','s',' ','N','e','w',' ', + 'R','o','m','a','n',0}; + static const WCHAR plainTextFont[] = {'C','o','u','r','i','e','r',' ','N','e','w',0}; + CHARFORMAT2W fmt; + LPCWSTR font; + + ZeroMemory(&fmt, sizeof(fmt)); + + fmt.cbSize = sizeof(fmt); + fmt.dwMask = CFM_FACE | CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE; + fmt.dwEffects = 0; + + if(fileFormat & SF_RTF) + font = richTextFont; + else + font = plainTextFont; + + lstrcpyW(fmt.szFaceName, font); + + SendMessageW(hEditorWnd, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM)&fmt); +} + +static void update_window(void) +{ + RECT rect; + + GetWindowRect(hMainWnd, &rect); + + (void) OnSize(hMainWnd, SIZE_RESTORED, MAKELONG(rect.bottom, rect.right)); +} + +static DWORD barState[2]; +static DWORD wordWrap[2]; + +static BOOL is_bar_visible(int bandId) +{ + return barState[reg_formatindex(fileFormat)] & (1 << bandId); +} + +static void store_bar_state(int bandId, BOOL show) +{ + int formatIndex = reg_formatindex(fileFormat); + + if(show) + barState[formatIndex] |= (1 << bandId); + else + barState[formatIndex] &= ~(1 << bandId); +} + +static void set_toolbar_state(int bandId, BOOL show) +{ + HWND hwndReBar = GetDlgItem(hMainWnd, IDC_REBAR); + + SendMessageW(hwndReBar, RB_SHOWBAND, SendMessageW(hwndReBar, RB_IDTOINDEX, bandId, 0), show); + + if(bandId == BANDID_TOOLBAR) + { + REBARBANDINFOW rbbinfo; + int index = SendMessageW(hwndReBar, RB_IDTOINDEX, BANDID_FORMATBAR, 0); + + rbbinfo.cbSize = sizeof(rbbinfo); + rbbinfo.fMask = RBBIM_STYLE; + + SendMessageW(hwndReBar, RB_GETBANDINFO, index, (LPARAM)&rbbinfo); + + if(!show) + rbbinfo.fStyle &= ~RBBS_BREAK; + else + rbbinfo.fStyle |= RBBS_BREAK; + + SendMessageW(hwndReBar, RB_SETBANDINFO, index, (LPARAM)&rbbinfo); + } + + if(bandId == BANDID_TOOLBAR || bandId == BANDID_FORMATBAR) + store_bar_state(bandId, show); +} + +static void set_statusbar_state(BOOL show) +{ + HWND hStatusWnd = GetDlgItem(hMainWnd, IDC_STATUSBAR); + + ShowWindow(hStatusWnd, show ? SW_SHOW : SW_HIDE); + store_bar_state(BANDID_STATUSBAR, show); +} + +static void set_bar_states(void) +{ + set_toolbar_state(BANDID_TOOLBAR, is_bar_visible(BANDID_TOOLBAR)); + set_toolbar_state(BANDID_FORMATBAR, is_bar_visible(BANDID_FORMATBAR)); + set_statusbar_state(is_bar_visible(BANDID_STATUSBAR)); + + update_window(); +} + +static HGLOBAL devMode; +static HGLOBAL devNames; + +static HDC make_dc(void) +{ + if(devNames && devMode) + { + LPDEVNAMES dn = GlobalLock(devNames); + LPDEVMODEW dm = GlobalLock(devMode); + HDC ret; + + ret = CreateDCW((LPWSTR)dn + dn->wDriverOffset, + (LPWSTR)dn + dn->wDeviceOffset, 0, dm); + + GlobalUnlock(dn); + GlobalUnlock(dm); + + return ret; + } else + { + return 0; + } +} + +static LONG twips_to_pixels(int twips, int dpi) +{ + float ret = ((float)twips / ((float)567 * 2.54)) * (float)dpi; + return (LONG)ret; +} + +static LONG devunits_to_twips(int units, int dpi) +{ + float ret = ((float)units / (float)dpi) * (float)567 * 2.54; + return (LONG)ret; +} + +static LONG centmm_to_twips(int mm) +{ + return MulDiv(mm, 567, 1000); +} + +static LONG twips_to_centmm(int twips) +{ + return MulDiv(twips, 1000, 567); +} + +static RECT get_print_rect(HDC hdc) +{ + RECT rc; + int width, height; + + if(hdc) + { + int dpiY = GetDeviceCaps(hdc, LOGPIXELSY); + int dpiX = GetDeviceCaps(hdc, LOGPIXELSX); + width = devunits_to_twips(GetDeviceCaps(hdc, PHYSICALWIDTH), dpiX); + height = devunits_to_twips(GetDeviceCaps(hdc, PHYSICALHEIGHT), dpiY); + } else + { + width = centmm_to_twips(18500); + height = centmm_to_twips(27000); + } + + rc.left = margins.left; + rc.right = width - margins.right; + rc.top = margins.top; + rc.bottom = height - margins.bottom; + + return rc; +} + +static void target_device(void) +{ + HDC hdc = make_dc(); + int width = 0; + int index = reg_formatindex(fileFormat); + + if(wordWrap[index] == ID_WORDWRAP_MARGIN) + { + RECT rc = get_print_rect(hdc); + width = rc.right; + } + + if(!hdc) + { + HDC hMaindc = GetDC(hMainWnd); + hdc = CreateCompatibleDC(hMaindc); + ReleaseDC(hMainWnd, hMaindc); + } + + SendMessageW(hEditorWnd, EM_SETTARGETDEVICE, (WPARAM)hdc, width); + + DeleteDC(hdc); +} + static void set_fileformat(WPARAM format) { fileFormat = format; + + set_bar_states(); + set_default_font(); + target_device(); } static void DoOpenFile(LPCWSTR szOpenFileName) @@ -538,6 +837,7 @@ static void DoOpenFile(LPCWSTR szOpenFileName) es.pfnCallback = stream_in; clear_formatting(); + set_fileformat(format); SendMessageW(hEditorWnd, EM_STREAMIN, format, (LPARAM)&es); CloseHandle(hFile); @@ -549,7 +849,6 @@ static void DoOpenFile(LPCWSTR szOpenFileName) lstrcpyW(wszFileName, szOpenFileName); SendMessageW(hEditorWnd, EM_SETMODIFY, FALSE, 0); registry_set_filelist(szOpenFileName); - set_fileformat(format); } static void DoSaveFile(LPCWSTR wszSaveFileName, WPARAM format) @@ -673,49 +972,574 @@ static BOOL prompt_save_changes(void) ret = MessageBoxW(hMainWnd, text, wszAppTitle, MB_YESNOCANCEL | MB_ICONEXCLAMATION); - HeapFree(GetProcessHeap(), 0, text); + HeapFree(GetProcessHeap(), 0, text); + + switch(ret) + { + case IDNO: + return TRUE; + + case IDYES: + if(wszFileName[0]) + DoSaveFile(wszFileName, fileFormat); + else + DialogSaveFile(); + return TRUE; + + default: + return FALSE; + } + } +} + +static void DialogOpenFile(void) +{ + OPENFILENAMEW ofn; + + WCHAR wszFile[MAX_PATH] = {'\0'}; + static const WCHAR wszDefExt[] = {'r','t','f','\0'}; + + ZeroMemory(&ofn, sizeof(ofn)); + + ofn.lStructSize = sizeof(ofn); + ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; + ofn.hwndOwner = hMainWnd; + ofn.lpstrFilter = wszFilter; + ofn.lpstrFile = wszFile; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrDefExt = wszDefExt; + ofn.nFilterIndex = fileformat_number(fileFormat)+1; + + if(GetOpenFileNameW(&ofn)) + { + if(prompt_save_changes()) + DoOpenFile(ofn.lpstrFile); + } +} + +static LPWSTR dialog_print_to_file(void) +{ + OPENFILENAMEW ofn; + static WCHAR file[MAX_PATH] = {'O','U','T','P','U','T','.','P','R','N',0}; + static const WCHAR defExt[] = {'P','R','N',0}; + + ZeroMemory(&ofn, sizeof(ofn)); + + ofn.lStructSize = sizeof(ofn); + ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; + ofn.hwndOwner = hMainWnd; + ofn.lpstrFilter = (LPWSTR)wszPrintFilter; + ofn.lpstrFile = (LPWSTR)file; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrDefExt = (LPWSTR)defExt; + + if(GetSaveFileNameW(&ofn)) + return (LPWSTR)file; + else + return FALSE; +} + +static int get_num_pages(FORMATRANGE fr) +{ + int page = 0; + + do + { + page++; + fr.chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, + (LPARAM)&fr); + } while(fr.chrg.cpMin < fr.chrg.cpMax); + + return page; +} + +static void char_from_pagenum(FORMATRANGE *fr, int page) +{ + int i; + + for(i = 1; i <= page; i++) + { + if(i == page) + break; + + fr->chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)fr); + } +} + +static void print(LPPRINTDLGW pd) +{ + FORMATRANGE fr; + DOCINFOW di; + int printedPages = 0; + + fr.hdc = pd->hDC; + fr.hdcTarget = pd->hDC; + + fr.rc = get_print_rect(fr.hdc); + fr.rcPage.left = 0; + fr.rcPage.right = fr.rc.right + margins.right; + fr.rcPage.top = 0; + fr.rcPage.bottom = fr.rc.bottom + margins.bottom; + + ZeroMemory(&di, sizeof(di)); + di.cbSize = sizeof(di); + di.lpszDocName = (LPWSTR)wszFileName; + + if(pd->Flags & PD_PRINTTOFILE) + { + di.lpszOutput = dialog_print_to_file(); + if(!di.lpszOutput) + return; + } + + if(pd->Flags & PD_SELECTION) + { + SendMessageW(hEditorWnd, EM_EXGETSEL, 0, (LPARAM)&fr.chrg); + } else + { + GETTEXTLENGTHEX gt; + gt.flags = GTL_DEFAULT; + gt.codepage = 1200; + fr.chrg.cpMin = 0; + fr.chrg.cpMax = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)>, 0); + + if(pd->Flags & PD_PAGENUMS) + char_from_pagenum(&fr, pd->nToPage); + } + + StartDocW(fr.hdc, &di); + do + { + if(StartPage(fr.hdc) <= 0) + break; + + fr.chrg.cpMin = SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)&fr); + + if(EndPage(fr.hdc) <= 0) + break; + + printedPages++; + if((pd->Flags & PD_PAGENUMS) && (printedPages > (pd->nToPage - pd->nFromPage))) + break; + } + while(fr.chrg.cpMin < fr.chrg.cpMax); + + EndDoc(fr.hdc); + SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, 0); + target_device(); +} + +static void dialog_printsetup(void) +{ + PAGESETUPDLGW ps; + + ZeroMemory(&ps, sizeof(ps)); + ps.lStructSize = sizeof(ps); + ps.hwndOwner = hMainWnd; + ps.Flags = PSD_INHUNDREDTHSOFMILLIMETERS | PSD_MARGINS; + ps.rtMargin.left = twips_to_centmm(margins.left); + ps.rtMargin.right = twips_to_centmm(margins.right); + ps.rtMargin.top = twips_to_centmm(margins.top); + ps.rtMargin.bottom = twips_to_centmm(margins.bottom); + ps.hDevMode = devMode; + ps.hDevNames = devNames; + + if(PageSetupDlgW(&ps)) + { + margins.left = centmm_to_twips(ps.rtMargin.left); + margins.right = centmm_to_twips(ps.rtMargin.right); + margins.top = centmm_to_twips(ps.rtMargin.top); + margins.bottom = centmm_to_twips(ps.rtMargin.bottom); + devMode = ps.hDevMode; + devNames = ps.hDevNames; + target_device(); + } +} + +static void get_default_printer_opts(void) +{ + PRINTDLGW pd; + ZeroMemory(&pd, sizeof(pd)); + + ZeroMemory(&pd, sizeof(pd)); + pd.lStructSize = sizeof(pd); + pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT; + pd.hwndOwner = hMainWnd; + pd.hDevMode = devMode; + + PrintDlgW(&pd); + + devMode = pd.hDevMode; + devNames = pd.hDevNames; +} + +static void print_quick(void) +{ + PRINTDLGW pd; + + ZeroMemory(&pd, sizeof(pd)); + pd.hDC = make_dc(); + + print(&pd); +} + +static void dialog_print(void) +{ + PRINTDLGW pd; + int from = 0; + int to = 0; + + ZeroMemory(&pd, sizeof(pd)); + pd.lStructSize = sizeof(pd); + pd.hwndOwner = hMainWnd; + pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE; + pd.nMinPage = 1; + pd.nMaxPage = -1; + pd.hDevMode = devMode; + pd.hDevNames = devNames; + + SendMessageW(hEditorWnd, EM_GETSEL, (WPARAM)&from, (LPARAM)&to); + if(from == to) + pd.Flags |= PD_NOSELECTION; + + if(PrintDlgW(&pd)) + { + devMode = pd.hDevMode; + devNames = pd.hDevNames; + print(&pd); + } +} + +typedef struct _previewinfo +{ + int page; + int pages; + HDC hdc; + HDC hdcSized; + RECT window; +} previewinfo, *ppreviewinfo; + +static previewinfo preview; + +static void preview_bar_show(BOOL show) +{ + HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR); + int i; + + if(show) + { + AddTextButton(hReBar, STRING_PREVIEW_PRINT, ID_PRINT, BANDID_PREVIEW_BTN1); + AddTextButton(hReBar, STRING_PREVIEW_NEXTPAGE, ID_PREVIEW_NEXTPAGE, BANDID_PREVIEW_BTN2); + AddTextButton(hReBar, STRING_PREVIEW_PREVPAGE, ID_PREVIEW_PREVPAGE, BANDID_PREVIEW_BTN3); + AddTextButton(hReBar, STRING_PREVIEW_CLOSE, ID_FILE_EXIT, BANDID_PREVIEW_BTN4); + } else + { + for(i = 0; i < PREVIEW_BUTTONS; i++) + SendMessageW(hReBar, RB_DELETEBAND, SendMessageW(hReBar, RB_IDTOINDEX, BANDID_PREVIEW_BTN1+i, 0), 0); + } +} + +static void preview_exit(void) +{ + HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hMainWnd, GWLP_HINSTANCE); + HMENU hMenu = LoadMenuW(hInstance, xszMainMenu); + + set_bar_states(); + preview.window.right = 0; + preview.window.bottom = 0; + preview.page = 0; + preview.pages = 0; + ShowWindow(hEditorWnd, TRUE); + + preview_bar_show(FALSE); + + SetMenu(hMainWnd, hMenu); + registry_read_filelist(hMainWnd); + + update_window(); +} + +static LRESULT print_preview(void) +{ + FORMATRANGE fr; + GETTEXTLENGTHEX gt; + HDC hdc; + RECT window, background; + HBITMAP hBitmapCapture, hBitmapScaled; + int bmWidth, bmHeight, bmNewWidth, bmNewHeight; + float ratioWidth, ratioHeight, ratio; + int xOffset, yOffset; + int barheight; + HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR); + PAINTSTRUCT ps; + + hdc = BeginPaint(hMainWnd, &ps); + GetClientRect(hMainWnd, &window); + + fr.hdcTarget = make_dc(); + fr.rc = get_print_rect(fr.hdcTarget); + fr.rcPage.left = 0; + fr.rcPage.top = 0; + fr.rcPage.bottom = fr.rc.bottom + margins.bottom; + fr.rcPage.right = fr.rc.right + margins.right; + + bmWidth = twips_to_pixels(fr.rcPage.right, GetDeviceCaps(hdc, LOGPIXELSX)); + bmHeight = twips_to_pixels(fr.rcPage.bottom, GetDeviceCaps(hdc, LOGPIXELSY)); + + hBitmapCapture = CreateCompatibleBitmap(hdc, bmWidth, bmHeight); + + if(!preview.hdc) + { + RECT paper; + + preview.hdc = CreateCompatibleDC(hdc); + fr.hdc = preview.hdc; + gt.flags = GTL_DEFAULT; + gt.codepage = 1200; + fr.chrg.cpMin = 0; + fr.chrg.cpMax = SendMessageW(hEditorWnd, EM_GETTEXTLENGTHEX, (WPARAM)>, 0); + + paper.left = 0; + paper.right = bmWidth; + paper.top = 0; + paper.bottom = bmHeight; + + if(!preview.pages) + preview.pages = get_num_pages(fr); + + SelectObject(preview.hdc, hBitmapCapture); + + char_from_pagenum(&fr, preview.page); + + FillRect(preview.hdc, &paper, GetStockObject(WHITE_BRUSH)); + SendMessageW(hEditorWnd, EM_FORMATRANGE, TRUE, (LPARAM)&fr); + SendMessageW(hEditorWnd, EM_FORMATRANGE, FALSE, 0); + + EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_PREVPAGE), preview.page > 1); + EnableWindow(GetDlgItem(hReBar, ID_PREVIEW_NEXTPAGE), preview.page < preview.pages); + } + + barheight = SendMessageW(hReBar, RB_GETBARHEIGHT, 0, 0); + ratioWidth = ((float)window.right - 20.0) / (float)bmHeight; + ratioHeight = ((float)window.bottom - 20.0 - (float)barheight) / (float)bmHeight; + + if(ratioWidth > ratioHeight) + ratio = ratioHeight; + else + ratio = ratioWidth; + + bmNewWidth = (int)((float)bmWidth * ratio); + bmNewHeight = (int)((float)bmHeight * ratio); + hBitmapScaled = CreateCompatibleBitmap(hdc, bmNewWidth, bmNewHeight); + + xOffset = ((window.right - bmNewWidth) / 2); + yOffset = ((window.bottom - bmNewHeight + barheight) / 2); + + if(window.right != preview.window.right || window.bottom != preview.window.bottom) + { + DeleteDC(preview.hdcSized), + preview.hdcSized = CreateCompatibleDC(hdc); + SelectObject(preview.hdcSized, hBitmapScaled); + + StretchBlt(preview.hdcSized, 0, 0, bmNewWidth, bmNewHeight, preview.hdc, 0, 0, bmWidth, bmHeight, SRCCOPY); + } + + window.top = barheight; + FillRect(hdc, &window, GetStockObject(GRAY_BRUSH)); + + SelectObject(hdc, hBitmapScaled); + + background.left = xOffset - 2; + background.right = xOffset + bmNewWidth + 2; + background.top = yOffset - 2; + background.bottom = yOffset + bmNewHeight + 2; + + FillRect(hdc, &background, GetStockObject(BLACK_BRUSH)); + + BitBlt(hdc, xOffset, yOffset, bmNewWidth, bmNewHeight, preview.hdcSized, 0, 0, SRCCOPY); + + DeleteDC(fr.hdcTarget); + preview.window = window; + + EndPaint(hMainWnd, &ps); + + return 0; +} + +static LRESULT preview_command(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + switch(LOWORD(wParam)) + { + case ID_FILE_EXIT: + PostMessageW(hMainWnd, WM_CLOSE, 0, 0); + break; - switch(ret) - { - case IDNO: - return TRUE; + case ID_PREVIEW_NEXTPAGE: + case ID_PREVIEW_PREVPAGE: + { + HWND hReBar = GetDlgItem(hMainWnd, IDC_REBAR); + RECT rc; - case IDYES: - if(wszFileName[0]) - DoSaveFile(wszFileName, fileFormat); + if(LOWORD(wParam) == ID_PREVIEW_NEXTPAGE) + preview.page++; else - DialogSaveFile(); - return TRUE; + preview.page--; - default: - return FALSE; - } + preview.hdc = 0; + preview.window.right = 0; + + GetClientRect(hMainWnd, &rc); + rc.top += SendMessageW(hReBar, RB_GETBARHEIGHT, 0, 0); + InvalidateRect(hMainWnd, &rc, TRUE); + } + break; + + case ID_PRINT: + dialog_print(); + preview_exit(); + break; } + + return 0; } -static void DialogOpenFile(void) + +static void dialog_about(void) { - OPENFILENAMEW ofn; + HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hMainWnd, GWLP_HINSTANCE); + HICON icon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_WORDPAD)); + ShellAboutW(hMainWnd, wszAppTitle, 0, icon); +} - WCHAR wszFile[MAX_PATH] = {'\0'}; - static const WCHAR wszDefExt[] = {'r','t','f','\0'}; +static INT_PTR CALLBACK formatopts_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + { + LPPROPSHEETPAGEW ps = (LPPROPSHEETPAGEW)lParam; + int wrap = -1; + char id[4]; + HWND hIdWnd = GetDlgItem(hWnd, IDC_PAGEFMT_ID); + + sprintf(id, "%d\n", (int)ps->lParam); + SetWindowTextA(hIdWnd, id); + if(wordWrap[ps->lParam] == ID_WORDWRAP_WINDOW) + wrap = IDC_PAGEFMT_WW; + else if(wordWrap[ps->lParam] == ID_WORDWRAP_MARGIN) + wrap = IDC_PAGEFMT_WM; + + if(wrap != -1) + CheckRadioButton(hWnd, IDC_PAGEFMT_WW, + IDC_PAGEFMT_WM, wrap); + + if(barState[ps->lParam] & (1 << BANDID_TOOLBAR)) + CheckDlgButton(hWnd, IDC_PAGEFMT_TB, TRUE); + if(barState[ps->lParam] & (1 << BANDID_FORMATBAR)) + CheckDlgButton(hWnd, IDC_PAGEFMT_FB, TRUE); + if(barState[ps->lParam] & (BANDID_STATUSBAR)) + CheckDlgButton(hWnd, IDC_PAGEFMT_SB, TRUE); + } + break; - ZeroMemory(&ofn, sizeof(ofn)); + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_PAGEFMT_WW: + case IDC_PAGEFMT_WM: + CheckRadioButton(hWnd, IDC_PAGEFMT_WW, IDC_PAGEFMT_WM, + LOWORD(wParam)); + break; - ofn.lStructSize = sizeof(ofn); - ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; - ofn.hwndOwner = hMainWnd; - ofn.lpstrFilter = wszFilter; - ofn.lpstrFile = wszFile; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrDefExt = wszDefExt; - ofn.nFilterIndex = fileformat_number(fileFormat)+1; + case IDC_PAGEFMT_TB: + case IDC_PAGEFMT_FB: + case IDC_PAGEFMT_SB: + CheckDlgButton(hWnd, LOWORD(wParam), + !IsDlgButtonChecked(hWnd, LOWORD(wParam))); + break; + } + break; + case WM_NOTIFY: + { + LPNMHDR header = (LPNMHDR)lParam; + if(header->code == PSN_APPLY) + { + HWND hIdWnd = GetDlgItem(hWnd, IDC_PAGEFMT_ID); + char sid[4]; + int id; + + GetWindowTextA(hIdWnd, sid, 4); + id = atoi(sid); + if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_WW)) + wordWrap[id] = ID_WORDWRAP_WINDOW; + else if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_WM)) + wordWrap[id] = ID_WORDWRAP_MARGIN; + + if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_TB)) + barState[id] |= (1 << BANDID_TOOLBAR); + else + barState[id] &= ~(1 << BANDID_TOOLBAR); + + if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_FB)) + barState[id] |= (1 << BANDID_FORMATBAR); + else + barState[id] &= ~(1 << BANDID_FORMATBAR); + + if(IsDlgButtonChecked(hWnd, IDC_PAGEFMT_SB)) + barState[id] |= (1 << BANDID_STATUSBAR); + else + barState[id] &= ~(1 << BANDID_STATUSBAR); + } + } + break; + } + return FALSE; +} - if(GetOpenFileNameW(&ofn)) +static void dialog_viewproperties(void) +{ + PROPSHEETPAGEW psp[2]; + PROPSHEETHEADERW psh; + int i; + HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hMainWnd, GWLP_HINSTANCE); + LPCPROPSHEETPAGEW ppsp = (LPCPROPSHEETPAGEW)&psp; + + psp[0].dwSize = sizeof(PROPSHEETPAGEW); + psp[0].dwFlags = PSP_USETITLE; + psp[0].pszTemplate = MAKEINTRESOURCEW(IDD_FORMATOPTS); + psp[0].pfnDlgProc = formatopts_proc; + psp[0].hInstance = hInstance; + psp[0].lParam = reg_formatindex(SF_TEXT); + psp[0].pfnCallback = NULL; + psp[0].pszTitle = MAKEINTRESOURCEW(STRING_VIEWPROPS_TEXT); + for(i = 1; i < sizeof(psp)/sizeof(psp[0]); i++) { - if(prompt_save_changes()) - DoOpenFile(ofn.lpstrFile); + psp[i].dwSize = psp[0].dwSize; + psp[i].dwFlags = psp[0].dwFlags; + psp[i].pszTemplate = psp[0].pszTemplate; + psp[i].pfnDlgProc = psp[0].pfnDlgProc; + psp[i].hInstance = psp[0].hInstance; + psp[i].lParam = reg_formatindex(SF_RTF); + psp[i].pfnCallback = psp[0].pfnCallback; + psp[i].pszTitle = MAKEINTRESOURCEW(STRING_VIEWPROPS_RICHTEXT); } + + psh.dwSize = sizeof(psh); + psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW; + psh.hwndParent = hMainWnd; + psh.hInstance = hInstance; + psh.pszCaption = MAKEINTRESOURCEW(STRING_VIEWPROPS_TITLE); + psh.nPages = sizeof(psp)/sizeof(psp[0]); + psh.ppsp = ppsp; + psh.pszIcon = MAKEINTRESOURCEW(IDI_WORDPAD); + + if(fileFormat & SF_RTF) + psh.nStartPage = 1; + else + psh.nStartPage = 0; + PropertySheetW(&psh); + set_bar_states(); + target_device(); } static void HandleCommandLine(LPWSTR cmdline) @@ -870,64 +1694,102 @@ static void dialog_find(LPFINDREPLACEW fr) hFindWnd = FindTextW(fr); } - -static void DoDefaultFont(void) +static void registry_read_options(void) { - static const WCHAR szFaceName[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n',0}; - CHARFORMAT2W fmt; - - ZeroMemory(&fmt, sizeof(fmt)); - - fmt.cbSize = sizeof(fmt); - fmt.dwMask = CFM_FACE | CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE; - fmt.dwEffects = 0; + HKEY hKey; + DWORD size = sizeof(RECT); - lstrcpyW(fmt.szFaceName, szFaceName); + if(registry_get_handle(&hKey, 0, key_options) != ERROR_SUCCESS || + RegQueryValueExW(hKey, var_pagemargin, 0, NULL, (LPBYTE)&margins, + &size) != ERROR_SUCCESS || size != sizeof(RECT)) + { + margins.top = 1417; + margins.bottom = 1417; + margins.left = 1757; + margins.right = 1757; + } - SendMessageW(hEditorWnd, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM)&fmt); + RegCloseKey(hKey); } -static void update_window(void) +static void registry_read_formatopts(int index, LPCWSTR key) { - RECT rect; + HKEY hKey; + DWORD action = 0; + BOOL fetched = FALSE; + barState[index] = 0; + wordWrap[index] = 0; - GetWindowRect(hMainWnd, &rect); + if(registry_get_handle(&hKey, &action, key) != ERROR_SUCCESS) + return; - (void) OnSize(hMainWnd, SIZE_RESTORED, MAKELONG(rect.bottom, rect.right)); -} + if(action == REG_OPENED_EXISTING_KEY) + { + DWORD size = sizeof(DWORD); -static void toggle_toolbar(int bandId) -{ - HWND hwndReBar = GetDlgItem(hMainWnd, IDC_REBAR); - REBARBANDINFOW rbbinfo; - BOOL hide = TRUE; + if(RegQueryValueExW(hKey, var_barstate0, 0, NULL, (LPBYTE)&barState[index], + &size) == ERROR_SUCCESS) + fetched = TRUE; + } - if(!hwndReBar) - return; + if(!fetched) + barState[index] = (1 << BANDID_TOOLBAR) | (1 << BANDID_FORMATBAR) | (1 << BANDID_RULER) | (1 << BANDID_STATUSBAR); - rbbinfo.cbSize = sizeof(rbbinfo); - rbbinfo.fMask = RBBIM_STYLE | RBBIM_SIZE; + if(index == reg_formatindex(SF_RTF)) + wordWrap[index] = ID_WORDWRAP_WINDOW; + else if(index == reg_formatindex(SF_TEXT)) + wordWrap[index] = ID_WORDWRAP_WINDOW; /* FIXME: should be ID_WORDWRAP_NONE once we support it */ - SendMessageW(hwndReBar, RB_GETBANDINFO, bandId, (LPARAM)&rbbinfo); + RegCloseKey(hKey); +} - if(rbbinfo.fStyle & RBBS_HIDDEN) - hide = FALSE; +static void registry_read_formatopts_all(void) +{ + registry_read_formatopts(reg_formatindex(SF_RTF), key_rtf); + registry_read_formatopts(reg_formatindex(SF_TEXT), key_text); +} - SendMessageW(hwndReBar, RB_SHOWBAND, bandId, hide ? 0 : 1); +static void registry_set_formatopts(int index, LPCWSTR key) +{ + HKEY hKey; + DWORD action = 0; - if(bandId == BANDID_TOOLBAR) + if(registry_get_handle(&hKey, &action, key) == ERROR_SUCCESS) { - rbbinfo.fMask ^= RBBIM_SIZE; + RegSetValueExW(hKey, var_barstate0, 0, REG_DWORD, (LPBYTE)&barState[index], + sizeof(DWORD)); - SendMessageW(hwndReBar, RB_GETBANDINFO, BANDID_FORMATBAR, (LPARAM)&rbbinfo); + RegCloseKey(hKey); + } +} - if(hide) - rbbinfo.fStyle ^= RBBS_BREAK; - else - rbbinfo.fStyle |= RBBS_BREAK; +static void registry_set_formatopts_all(void) +{ + registry_set_formatopts(reg_formatindex(SF_RTF), key_rtf); + registry_set_formatopts(reg_formatindex(SF_TEXT), key_text); +} - SendMessageW(hwndReBar, RB_SETBANDINFO, BANDID_FORMATBAR, (LPARAM)&rbbinfo); - } +static int current_units_to_twips(float number) +{ + int twips = (int)(number * 567); + return twips; +} + +static void append_current_units(LPWSTR buffer) +{ + static const WCHAR space[] = {' '}; + lstrcatW(buffer, space); + lstrcatW(buffer, units_cmW); +} + +static void number_with_units(LPWSTR buffer, int number) +{ + float converted = (float)number / 567; + char string[MAX_STRING_LEN]; + + sprintf(string, "%.2f ", converted); + lstrcatA(string, units_cmA); + MultiByteToWideChar(CP_ACP, 0, string, -1, buffer, MAX_STRING_LEN); } BOOL CALLBACK datetime_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) @@ -1024,6 +1886,254 @@ BOOL CALLBACK newfile_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam return FALSE; } +static INT_PTR CALLBACK paraformat_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + { + HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hMainWnd, + GWLP_HINSTANCE); + WCHAR buffer[MAX_STRING_LEN]; + HWND hListWnd = GetDlgItem(hWnd, IDC_PARA_ALIGN); + HWND hLeftWnd = GetDlgItem(hWnd, IDC_PARA_LEFT); + HWND hRightWnd = GetDlgItem(hWnd, IDC_PARA_RIGHT); + HWND hFirstWnd = GetDlgItem(hWnd, IDC_PARA_FIRST); + PARAFORMAT2 pf; + int index = 0; + + LoadStringW(hInstance, STRING_ALIGN_LEFT, buffer, + MAX_STRING_LEN); + SendMessageW(hListWnd, CB_ADDSTRING, 0, (LPARAM)buffer); + LoadStringW(hInstance, STRING_ALIGN_RIGHT, buffer, + MAX_STRING_LEN); + SendMessageW(hListWnd, CB_ADDSTRING, 0, (LPARAM)buffer); + LoadStringW(hInstance, STRING_ALIGN_CENTER, buffer, + MAX_STRING_LEN); + SendMessageW(hListWnd, CB_ADDSTRING, 0, (LPARAM)buffer); + + pf.cbSize = sizeof(pf); + pf.dwMask = PFM_ALIGNMENT | PFM_OFFSET | PFM_RIGHTINDENT | + PFM_OFFSETINDENT; + SendMessageW(hEditorWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf); + + if(pf.wAlignment == PFA_RIGHT) + index ++; + else if(pf.wAlignment == PFA_CENTER) + index += 2; + + SendMessageW(hListWnd, CB_SETCURSEL, index, 0); + + number_with_units(buffer, pf.dxOffset); + SetWindowTextW(hLeftWnd, buffer); + number_with_units(buffer, pf.dxRightIndent); + SetWindowTextW(hRightWnd, buffer); + number_with_units(buffer, pf.dxStartIndent - pf.dxOffset); + SetWindowTextW(hFirstWnd, buffer); + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDOK: + { + HWND hLeftWnd = GetDlgItem(hWnd, IDC_PARA_LEFT); + HWND hRightWnd = GetDlgItem(hWnd, IDC_PARA_RIGHT); + HWND hFirstWnd = GetDlgItem(hWnd, IDC_PARA_FIRST); + WCHAR buffer[MAX_STRING_LEN]; + float num; + int ret = 0; + PARAFORMAT pf; + + GetWindowTextW(hLeftWnd, buffer, MAX_STRING_LEN); + if(number_from_string(buffer, &num, TRUE)) + ret++; + pf.dxOffset = current_units_to_twips(num); + GetWindowTextW(hRightWnd, buffer, MAX_STRING_LEN); + if(number_from_string(buffer, &num, TRUE)) + ret++; + pf.dxRightIndent = current_units_to_twips(num); + GetWindowTextW(hFirstWnd, buffer, MAX_STRING_LEN); + if(number_from_string(buffer, &num, TRUE)) + ret++; + pf.dxStartIndent = current_units_to_twips(num); + + if(ret != 3) + { + MessageBoxW(hMainWnd, MAKEINTRESOURCEW(STRING_INVALID_NUMBER), + wszAppTitle, MB_OK | MB_ICONASTERISK); + return FALSE; + } else + { + pf.dxStartIndent = pf.dxStartIndent + pf.dxOffset; + pf.cbSize = sizeof(pf); + pf.dwMask = PFM_OFFSET | PFM_OFFSETINDENT | PFM_RIGHTINDENT; + SendMessageW(hEditorWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf); + } + } + /* Fall through */ + + case IDCANCEL: + EndDialog(hWnd, wParam); + return TRUE; + } + } + return FALSE; +} + +static INT_PTR CALLBACK tabstops_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + { + HWND hTabWnd = GetDlgItem(hWnd, IDC_TABSTOPS); + PARAFORMAT pf; + WCHAR buffer[MAX_STRING_LEN]; + int i; + + pf.cbSize = sizeof(pf); + pf.dwMask = PFM_TABSTOPS; + SendMessageW(hEditorWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf); + SendMessageW(hTabWnd, CB_LIMITTEXT, MAX_STRING_LEN-1, 0); + + for(i = 0; i < pf.cTabCount; i++) + { + number_with_units(buffer, pf.rgxTabs[i]); + SendMessageW(hTabWnd, CB_ADDSTRING, 0, (LPARAM)&buffer); + } + SetFocus(hTabWnd); + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_TABSTOPS: + { + HWND hTabWnd = (HWND)lParam; + HWND hAddWnd = GetDlgItem(hWnd, ID_TAB_ADD); + HWND hDelWnd = GetDlgItem(hWnd, ID_TAB_DEL); + HWND hEmptyWnd = GetDlgItem(hWnd, ID_TAB_EMPTY); + + if(GetWindowTextLengthW(hTabWnd)) + EnableWindow(hAddWnd, TRUE); + else + EnableWindow(hAddWnd, FALSE); + + if(SendMessageW(hTabWnd, CB_GETCOUNT, 0, 0)) + { + EnableWindow(hEmptyWnd, TRUE); + + if(SendMessageW(hTabWnd, CB_GETCURSEL, 0, 0) == CB_ERR) + EnableWindow(hDelWnd, FALSE); + else + EnableWindow(hDelWnd, TRUE); + } else + { + EnableWindow(hEmptyWnd, FALSE); + } + } + break; + + case ID_TAB_ADD: + { + HWND hTabWnd = GetDlgItem(hWnd, IDC_TABSTOPS); + WCHAR buffer[MAX_STRING_LEN]; + + GetWindowTextW(hTabWnd, buffer, MAX_STRING_LEN); + append_current_units(buffer); + + if(SendMessageW(hTabWnd, CB_FINDSTRINGEXACT, -1, (LPARAM)&buffer) == CB_ERR) + { + float number = 0; + + if(!number_from_string(buffer, &number, TRUE)) + { + MessageBoxW(hWnd, MAKEINTRESOURCEW(STRING_INVALID_NUMBER), + wszAppTitle, MB_OK | MB_ICONINFORMATION); + } else + { + SendMessageW(hTabWnd, CB_ADDSTRING, 0, (LPARAM)&buffer); + SetWindowTextW(hTabWnd, 0); + } + } + SetFocus(hTabWnd); + } + break; + + case ID_TAB_DEL: + { + HWND hTabWnd = GetDlgItem(hWnd, IDC_TABSTOPS); + LRESULT ret; + ret = SendMessageW(hTabWnd, CB_GETCURSEL, 0, 0); + if(ret != CB_ERR) + SendMessageW(hTabWnd, CB_DELETESTRING, ret, 0); + } + break; + + case ID_TAB_EMPTY: + { + HWND hTabWnd = GetDlgItem(hWnd, IDC_TABSTOPS); + SendMessageW(hTabWnd, CB_RESETCONTENT, 0, 0); + SetFocus(hTabWnd); + } + break; + + case IDOK: + { + HWND hTabWnd = GetDlgItem(hWnd, IDC_TABSTOPS); + int i; + WCHAR buffer[MAX_STRING_LEN]; + PARAFORMAT pf; + float number; + + pf.cbSize = sizeof(pf); + pf.dwMask = PFM_TABSTOPS; + + for(i = 0; SendMessageW(hTabWnd, CB_GETLBTEXT, i, + (LPARAM)&buffer) != CB_ERR && + i < MAX_TAB_STOPS; i++) + { + number_from_string(buffer, &number, TRUE); + pf.rgxTabs[i] = current_units_to_twips(number); + } + pf.cTabCount = i; + SendMessageW(hEditorWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf); + } + /* Fall through */ + case IDCANCEL: + EndDialog(hWnd, wParam); + return TRUE; + } + } + return FALSE; +} + +static int context_menu(LPARAM lParam) +{ + int x = (int)(short)LOWORD(lParam); + int y = (int)(short)HIWORD(lParam); + HMENU hPop = GetSubMenu(hPopupMenu, 0); + + if(x == -1) + { + int from = 0, to = 0; + POINTL pt; + SendMessageW(hEditorWnd, EM_GETSEL, (WPARAM)&from, (LPARAM)&to); + SendMessageW(hEditorWnd, EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)to); + ClientToScreen(hEditorWnd, (POINT*)&pt); + x = pt.x; + y = pt.y; + } + + TrackPopupMenu(hPop, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON, + x, y, 0, hMainWnd, 0); + + return 0; +} + static LRESULT OnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam) { HWND hToolBarWnd, hFormatBarWnd, hReBarWnd; @@ -1062,7 +2172,7 @@ static LRESULT OnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam) AddButton(hToolBarWnd, nStdBitmaps+STD_FILEOPEN, ID_FILE_OPEN); AddButton(hToolBarWnd, nStdBitmaps+STD_FILESAVE, ID_FILE_SAVE); AddSeparator(hToolBarWnd); - AddButton(hToolBarWnd, nStdBitmaps+STD_PRINT, ID_PRINT); + AddButton(hToolBarWnd, nStdBitmaps+STD_PRINT, ID_PRINT_QUICK); AddButton(hToolBarWnd, nStdBitmaps+STD_PRINTPRE, ID_PREVIEW); AddSeparator(hToolBarWnd); AddButton(hToolBarWnd, nStdBitmaps+STD_FIND, ID_FIND); @@ -1078,14 +2188,15 @@ static LRESULT OnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam) SendMessageW(hToolBarWnd, TB_AUTOSIZE, 0, 0); rbb.cbSize = sizeof(rbb); - rbb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_STYLE; + rbb.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_STYLE | RBBIM_ID; rbb.fStyle = RBBS_CHILDEDGE | RBBS_BREAK | RBBS_NOGRIPPER; rbb.cx = 0; rbb.hwndChild = hToolBarWnd; rbb.cxMinChild = 0; rbb.cyChild = rbb.cyMinChild = HIWORD(SendMessageW(hToolBarWnd, TB_GETBUTTONSIZE, 0, 0)); + rbb.wID = BANDID_TOOLBAR; - SendMessageW(hReBarWnd, RB_INSERTBAND, BANDID_TOOLBAR, (LPARAM)&rbb); + SendMessageW(hReBarWnd, RB_INSERTBAND, -1, (LPARAM)&rbb); hFormatBarWnd = CreateToolbarEx(hReBarWnd, CCS_NOPARENTALIGN | CCS_NOMOVEY | WS_VISIBLE | TBSTYLE_TOOLTIPS | TBSTYLE_BUTTON, @@ -1104,8 +2215,9 @@ static LRESULT OnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam) SendMessageW(hFormatBarWnd, TB_AUTOSIZE, 0, 0); rbb.hwndChild = hFormatBarWnd; + rbb.wID = BANDID_FORMATBAR; - SendMessageW(hReBarWnd, RB_INSERTBAND, BANDID_FORMATBAR, (LPARAM)&rbb); + SendMessageW(hReBarWnd, RB_INSERTBAND, -1, (LPARAM)&rbb); hDLL = LoadLibraryW(wszRichEditDll); if(!hDLL) @@ -1116,7 +2228,7 @@ static LRESULT OnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam) } hEditorWnd = CreateWindowExW(WS_EX_CLIENTEDGE, wszRichEditClass, NULL, - WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_AUTOVSCROLL|ES_WANTRETURN|WS_VSCROLL, + WS_CHILD|WS_VISIBLE|ECO_SELECTIONBAR|ES_MULTILINE|ES_AUTOVSCROLL|ES_WANTRETURN|WS_VSCROLL, 0, 0, 1000, 100, hWnd, (HMENU)IDC_EDITOR, hInstance, NULL); if (!hEditorWnd) @@ -1129,7 +2241,7 @@ static LRESULT OnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam) SetFocus(hEditorWnd); SendMessageW(hEditorWnd, EM_SETEVENTMASK, 0, ENM_SELCHANGE); - DoDefaultFont(); + set_default_font(); DoLoadStrings(); SendMessageW(hEditorWnd, EM_SETMODIFY, FALSE, 0); @@ -1137,6 +2249,9 @@ static LRESULT OnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam) ID_FINDMSGSTRING = RegisterWindowMessageW(FINDMSGSTRINGW); registry_read_filelist(hWnd); + registry_read_formatopts_all(); + registry_read_options(); + DragAcceptFiles(hWnd, TRUE); return 0; } @@ -1219,7 +2334,6 @@ static LRESULT OnNotify( HWND hWnd, WPARAM wParam, LPARAM lParam) static LRESULT OnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam) { HWND hwndEditor = GetDlgItem(hWnd, IDC_EDITOR); - HWND hwndStatus = GetDlgItem(hWnd, IDC_STATUSBAR); static FINDREPLACEW findreplace; if ((HWND)lParam == hwndEditor) @@ -1247,12 +2361,12 @@ static LRESULT OnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam) set_caption(NULL); wszFileName[0] = '\0'; + clear_formatting(); + st.flags = ST_DEFAULT; st.codepage = 1200; SendMessageW(hEditorWnd, EM_SETTEXTEX, (WPARAM)&st, 0); - clear_formatting(); - SendMessageW(hEditorWnd, EM_SETMODIFY, FALSE, 0); set_fileformat(ret); } @@ -1300,14 +2414,34 @@ static LRESULT OnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam) break; case ID_PRINT: + dialog_print(); + break; + + case ID_PRINT_QUICK: + print_quick(); + break; + case ID_PREVIEW: { - static const WCHAR wszNotImplemented[] = {'N','o','t',' ', - 'i','m','p','l','e','m','e','n','t','e','d','\0'}; - MessageBoxW(hWnd, wszNotImplemented, wszAppTitle, MB_OK); + int index = reg_formatindex(fileFormat); + DWORD tmp = barState[index]; + barState[index] = 0; + set_bar_states(); + barState[index] = tmp; + ShowWindow(hEditorWnd, FALSE); + preview_bar_show(TRUE); + + preview.page = 1; + preview.hdc = 0; + SetMenu(hWnd, NULL); + InvalidateRect(0, 0, TRUE); } break; + case ID_PRINTSETUP: + dialog_printsetup(); + break; + case ID_FORMAT_BOLD: case ID_FORMAT_ITALIC: case ID_FORMAT_UNDERLINE: @@ -1489,17 +2623,17 @@ static LRESULT OnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam) break; case ID_TOGGLE_TOOLBAR: - toggle_toolbar(BANDID_TOOLBAR); + set_toolbar_state(BANDID_TOOLBAR, !is_bar_visible(BANDID_TOOLBAR)); update_window(); break; case ID_TOGGLE_FORMATBAR: - toggle_toolbar(BANDID_FORMATBAR); + set_toolbar_state(BANDID_FORMATBAR, !is_bar_visible(BANDID_FORMATBAR)); update_window(); break; case ID_TOGGLE_STATUSBAR: - ShowWindow(hwndStatus, IsWindowVisible(hwndStatus) ? SW_HIDE : SW_SHOW); + set_statusbar_state(!is_bar_visible(BANDID_STATUSBAR)); update_window(); break; @@ -1510,6 +2644,29 @@ static LRESULT OnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam) break; } + case ID_PARAFORMAT: + { + HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE); + DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_PARAFORMAT), hWnd, + paraformat_proc); + } + break; + + case ID_TABSTOPS: + { + HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE); + DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_TABSTOPS), hWnd, tabstops_proc); + } + break; + + case ID_ABOUT: + dialog_about(); + break; + + case ID_VIEWPROPERTIES: + dialog_viewproperties(); + break; + default: SendMessageW(hwndEditor, WM_COMMAND, wParam, lParam); break; @@ -1521,11 +2678,9 @@ static LRESULT OnInitPopupMenu( HWND hWnd, WPARAM wParam, LPARAM lParam ) { HMENU hMenu = (HMENU)wParam; HWND hwndEditor = GetDlgItem(hWnd, IDC_EDITOR); - HWND hwndReBar = GetDlgItem(hWnd, IDC_REBAR); HWND hwndStatus = GetDlgItem(hWnd, IDC_STATUSBAR); PARAFORMAT pf; int nAlignment = -1; - REBARBANDINFOW rbbinfo; int selFrom, selTo; GETTEXTLENGTHEX gt; LRESULT textLength; @@ -1556,17 +2711,11 @@ static LRESULT OnInitPopupMenu( HWND hWnd, WPARAM wParam, LPARAM lParam ) EnableMenuItem(hMenu, ID_EDIT_REDO, MF_BYCOMMAND|(SendMessageW(hwndEditor, EM_CANREDO, 0, 0)) ? MF_ENABLED : MF_GRAYED); - rbbinfo.cbSize = sizeof(rbbinfo); - rbbinfo.fMask = RBBIM_STYLE; - SendMessageW(hwndReBar, RB_GETBANDINFO, BANDID_TOOLBAR, (LPARAM)&rbbinfo); - - CheckMenuItem(hMenu, ID_TOGGLE_TOOLBAR, MF_BYCOMMAND|(rbbinfo.fStyle & RBBS_HIDDEN) ? - MF_UNCHECKED : MF_CHECKED); - - SendMessageW(hwndReBar, RB_GETBANDINFO, BANDID_FORMATBAR, (LPARAM)&rbbinfo); + CheckMenuItem(hMenu, ID_TOGGLE_TOOLBAR, MF_BYCOMMAND|(is_bar_visible(BANDID_TOOLBAR)) ? + MF_CHECKED : MF_UNCHECKED); - CheckMenuItem(hMenu, ID_TOGGLE_FORMATBAR, MF_BYCOMMAND|(rbbinfo.fStyle & RBBS_HIDDEN) ? - MF_UNCHECKED : MF_CHECKED); + CheckMenuItem(hMenu, ID_TOGGLE_FORMATBAR, MF_BYCOMMAND|(is_bar_visible(BANDID_FORMATBAR)) ? + MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hMenu, ID_TOGGLE_STATUSBAR, MF_BYCOMMAND|IsWindowVisible(hwndStatus) ? MF_CHECKED : MF_UNCHECKED); @@ -1594,7 +2743,6 @@ static LRESULT OnSize( HWND hWnd, WPARAM wParam, LPARAM lParam ) HWND hwndStatusBar = GetDlgItem(hWnd, IDC_STATUSBAR); HWND hwndReBar = GetDlgItem(hWnd, IDC_REBAR); int rebarHeight = 0; - REBARBANDINFOW rbbinfo; int rebarRows = 2; if (hwndStatusBar) @@ -1611,15 +2759,10 @@ static LRESULT OnSize( HWND hWnd, WPARAM wParam, LPARAM lParam ) } if (hwndReBar) { - rbbinfo.cbSize = sizeof(rbbinfo); - rbbinfo.fMask = RBBIM_STYLE; - - SendMessageW(hwndReBar, RB_GETBANDINFO, BANDID_TOOLBAR, (LPARAM)&rbbinfo); - if(rbbinfo.fStyle & RBBS_HIDDEN) + if(!is_bar_visible(BANDID_TOOLBAR)) rebarRows--; - SendMessageW(hwndReBar, RB_GETBANDINFO, BANDID_FORMATBAR, (LPARAM)&rbbinfo); - if(rbbinfo.fStyle & RBBS_HIDDEN) + if(!is_bar_visible(BANDID_FORMATBAR)) rebarRows--; rebarHeight = rebarRows ? SendMessageW(hwndReBar, RB_GETBARHEIGHT, 0, 0) : 0; @@ -1655,16 +2798,23 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara return OnNotify( hWnd, wParam, lParam ); case WM_COMMAND: - return OnCommand( hWnd, wParam, lParam ); + if(preview.page) + return preview_command( hWnd, wParam, lParam ); + else + return OnCommand( hWnd, wParam, lParam ); case WM_DESTROY: PostQuitMessage(0); break; case WM_CLOSE: - if(prompt_save_changes()) + if(preview.page) + { + preview_exit(); + } else if(prompt_save_changes()) { - registry_set_winrect(); + registry_set_options(); + registry_set_formatopts_all(); PostQuitMessage(0); } break; @@ -1680,6 +2830,28 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara case WM_SIZE: return OnSize( hWnd, wParam, lParam ); + case WM_CONTEXTMENU: + if((HWND)wParam == hEditorWnd) + return context_menu(lParam); + else + return DefWindowProcW(hWnd, msg, wParam, lParam); + + case WM_DROPFILES: + { + WCHAR file[MAX_PATH]; + DragQueryFileW((HDROP)wParam, 0, file, MAX_PATH); + DragFinish((HDROP)wParam); + + if(prompt_save_changes()) + DoOpenFile(file); + } + break; + case WM_PAINT: + if(preview.page) + return print_preview(); + else + return DefWindowProcW(hWnd, msg, wParam, lParam); + default: return DefWindowProcW(hWnd, msg, wParam, lParam); } @@ -1719,6 +2891,10 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hOldInstance, LPSTR szCmdPar ShowWindow(hMainWnd, SW_SHOWDEFAULT); set_caption(NULL); + set_bar_states(); + hPopupMenu = LoadMenuW(hInstance, MAKEINTRESOURCEW(IDM_POPUP)); + get_default_printer_opts(); + target_device(); HandleCommandLine(GetCommandLineW()); diff --git a/tools/winapi/win32.api b/tools/winapi/win32.api index d7725616226..d61bc74b4ec 100644 --- a/tools/winapi/win32.api +++ b/tools/winapi/win32.api @@ -4279,7 +4279,6 @@ UUID_VECTOR * ULONG * struct IRpcChannelBuffer * struct IRpcStubBuffer * -char * char ** twr_t * twr_t ** @@ -4295,6 +4294,7 @@ void %str RPC_CSTR +char * %wstr @@ -4987,6 +4987,21 @@ TW_UINT32 TW_MEMREF pTW_IDENTITY +%%url.dll + +%long + +BOOL +DWORD +HRESULT +HWND +int + +%str + +LPCSTR +LPSTR + %%urlmon.dll %long -- 2.11.4.GIT