Mercurial > install
changeset 13:2c122663858c default tip
Update OS/2 and Windows Dynamic Windows... change for using ace 2.0
author | Brian Smith <brian@dbsoft.org> |
---|---|
date | Thu, 26 Sep 2019 17:40:21 -0500 |
parents | 840ef4182857 |
children | |
files | dw.h os2/dw.c win/dw.c |
diffstat | 3 files changed, 2015 insertions(+), 1015 deletions(-) [+] |
line wrap: on
line diff
--- a/dw.h Wed Sep 26 23:31:24 2012 -0500 +++ b/dw.h Thu Sep 26 17:40:21 2019 -0500 @@ -1,11 +1,11 @@ -/* $Id: dw.h 1804 2012-09-24 23:24:25Z bsmith $ */ +/* $Id: dw.h 2001 2019-09-16 19:12:39Z bsmith $ */ #ifndef _H_DW #define _H_DW /* Dynamic Windows version numbers */ -#define DW_MAJOR_VERSION 2 -#define DW_MINOR_VERSION 4 +#define DW_MAJOR_VERSION 3 +#define DW_MINOR_VERSION 0 #define DW_SUB_VERSION 0 #if !defined(__PHOTON__) @@ -143,6 +143,8 @@ #define DW_FCF_AUTOICON FCF_AUTOICON #define DW_FCF_MAXIMIZE WS_MAXIMIZED #define DW_FCF_MINIMIZE WS_MINIMIZED +#define DW_FCF_TEXTURED 0 +#define DW_FCF_FULLSCREEN 0 #define DW_CFA_BITMAPORICON CFA_BITMAPORICON #define DW_CFA_STRING CFA_STRING @@ -159,6 +161,8 @@ #define DW_CRA_SELECTED CRA_SELECTED #define DW_CRA_CURSORED CRA_CURSORED +#define DW_CR_RETDATA (1 << 10) + #define DW_LS_MULTIPLESEL LS_MULTIPLESEL #define DW_LIT_NONE -1 @@ -255,6 +259,36 @@ extern HAB dwhab; extern HMQ dwhmq; + +#include <stdio.h> + +/* Mostly safe but slow snprintf() for compilers that don't have it... + * like VisualAge. So we can write safe code and still use VAC to test. + */ +#if defined(__IBMC__) && !defined(snprintf) +#include <stdarg.h> +#include <string.h> +#include <stdlib.h> +static int _dw_snprintf(char *str, size_t size, const char *format, ...) +{ + va_list args; + char *outbuf = calloc(1, size + strlen(format) + 1024); + int retval = -1; + + if(outbuf) + { + va_start(args, format); + vsprintf(outbuf, format, args); + va_end(args); + retval = strlen(outbuf); + strncpy(str, outbuf, size); + free(outbuf); + } + return retval; +} +#define snprintf _dw_snprintf +#endif + #endif #if defined(__MAC__) @@ -353,6 +387,8 @@ #define DW_FCF_AUTOICON 0 #define DW_FCF_MAXIMIZE 0 #define DW_FCF_MINIMIZE 0 +#define DW_FCF_TEXTURED (1 << 8) /* NSTexturedBackgroundWindowMask */ +#define DW_FCF_FULLSCREEN (1 << 4) #define DW_CFA_BITMAPORICON 1 #define DW_CFA_STRING (1 << 1) @@ -369,6 +405,8 @@ #define DW_CRA_SELECTED 1 #define DW_CRA_CURSORED (1 << 1) +#define DW_CR_RETDATA (1 << 10) + #define DW_LS_MULTIPLESEL 1 #define DW_LIT_NONE -1 @@ -483,6 +521,7 @@ /* Windows specific section */ #if defined(__WIN32__) || defined(WINNT) +#include <winsock2.h> #include <windows.h> #include <commctrl.h> @@ -492,6 +531,7 @@ # else # define API _cdecl #endif +#define DWSIGNAL _cdecl #endif #define DW_DT_LEFT SS_LEFTNOWORDWRAP @@ -529,6 +569,8 @@ #define DW_FCF_MAXIMIZE WS_MAXIMIZE #define DW_FCF_MINIMIZE WS_MINIMIZE #define DW_FCF_COMPOSITED 1 +#define DW_FCF_TEXTURED 0 +#define DW_FCF_FULLSCREEN (1 << 2) #define DW_CFA_BITMAPORICON 1 #define DW_CFA_STRING (1 << 1) @@ -545,6 +587,8 @@ #define DW_CRA_SELECTED LVNI_SELECTED #define DW_CRA_CURSORED LVNI_FOCUSED +#define DW_CR_RETDATA (1 << 10) + #define DW_LS_MULTIPLESEL LBS_MULTIPLESEL #define DW_LIT_NONE -1 @@ -638,6 +682,7 @@ typedef struct _box { #if defined(__WIN32__) || defined(WINNT) ColorInfo cinfo; + int fullscreen; #elif defined(__OS2__) || defined(__EMX__) PFNWP oldproc; UserData *root; @@ -791,6 +836,8 @@ #define DW_FCF_AUTOICON (Ph_WM_RENDER_ASICON | ~Ph_WM_RENDER_ASAPP) #define DW_FCF_MAXIMIZE 0 #define DW_FCF_MINIMIZE 0 +#define DW_FCF_TEXTURED 0 +#define DW_FCF_FULLSCREEN 0 #define DW_CFA_BITMAPORICON 1 #define DW_CFA_STRING (1 << 1) @@ -807,6 +854,8 @@ #define DW_CRA_SELECTED 1 #define DW_CRA_CURSORED (1 << 1) +#define DW_CR_RETDATA (1 << 10) + #define DW_LS_MULTIPLESEL 1 #define DW_LIT_NONE -1 @@ -924,6 +973,7 @@ #else /* GTK Specific section */ +#define _GNU_SOURCE #include <gtk/gtk.h> #ifdef GDK_WINDOWING_X11 # include <gdk/gdkx.h> @@ -973,6 +1023,8 @@ #define DW_FCF_MAXIMIZE (1 << 19) #define DW_FCF_MINIMIZE (1 << 20) #define DW_FCF_CLOSEBUTTON (1 << 21) +#define DW_FCF_TEXTURED 0 +#define DW_FCF_FULLSCREEN (1 << 22) #define DW_CFA_BITMAPORICON 1 #define DW_CFA_STRING (1 << 1) @@ -989,6 +1041,8 @@ #define DW_CRA_SELECTED 1 #define DW_CRA_CURSORED (1 << 1) +#define DW_CR_RETDATA (1 << 10) + #define DW_LS_MULTIPLESEL 1 #define DW_LIT_NONE -1 @@ -1350,11 +1404,19 @@ #define DW_RGB(a, b, c) (0xF0000000 | (a) | (b) << 8 | (c) << 16) #endif +/* Menu convenience paramaters */ #define DW_MENU_SEPARATOR "" #define DW_NOMENU 0 #define DW_MENU_AUTO 0 #define DW_MENU_POPUP (unsigned long)-1 +/* Convenience parameters for various types */ +#define DW_NOHWND 0 +#define DW_NOHTIMER 0 +#define DW_NOHPRINT 0 +#define DW_NOHPIXMAP 0 +#define DW_NOHICN 0 + #define DW_PERCENT_INDETERMINATE ((unsigned int)-1) /* Return value error codes */ @@ -1381,17 +1443,33 @@ #define DW_DRAW_FULL (1 << 1) #define DW_DRAW_NOAA (1 << 2) +/* MLE Completion flags */ +#define DW_MLE_COMPLETE_TEXT 1 +#define DW_MLE_COMPLETE_DASH (1 << 1) +#define DW_MLE_COMPLETE_QUOTE (1 << 2) + /* Macro for casting resource IDs to HICN */ #define DW_RESOURCE(a) (a < 65536 ? (HICN)a : (HICN)0) #include <limits.h> /* Macros for converting from INT/UINT to and from POINTER without compiler warnings */ -#if LONG_MAX > INT_MAX +#if _MSC_VER > 1500 || (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 30100 || defined(__has_extension) +#include <stdint.h> +/* There has got to be a better way to check for the intptr_t type.... + * for now just include valid versions of Visual C and GCC plus clang. + */ +#define DW_INT_TO_POINTER(a) ((void *)(intptr_t)a) +#define DW_POINTER_TO_INT(a) ((int)(intptr_t)a) +#define DW_UINT_TO_POINTER(a) ((void *)(uintptr_t)a) +#define DW_POINTER_TO_UINT(a) ((unsigned int)(uintptr_t)a) +#elif ULONG_MAX > UINT_MAX +/* If no intptr_t... ULONG is often bigger than UINT */ #define DW_INT_TO_POINTER(a) ((void *)(long)a) #define DW_POINTER_TO_INT(a) ((int)(long)a) #define DW_UINT_TO_POINTER(a) ((void *)(unsigned long)a) #define DW_POINTER_TO_UINT(a) ((unsigned int)(unsigned long)a) #else +/* Otherwise just fall back to standard casts */ #define DW_INT_TO_POINTER(a) ((void *)a) #define DW_POINTER_TO_INT(a) ((int)a) #define DW_UINT_TO_POINTER(a) ((void *)a) @@ -1407,7 +1485,9 @@ #define API #endif +#ifndef DWSIGNAL #define DWSIGNAL API +#endif /* Constants for sizing scrolled widgets */ #define _DW_SCROLLED_MIN_WIDTH 100 @@ -1437,20 +1517,20 @@ #endif /* Visual C */ -#if defined(_MSC_VER) +#if defined(_MSC_VER) # if _MSC_VER >= 1400 # define DW_DEPRECATED(func, message) __declspec(deprecated(message)) func # endif /* Clang */ #elif defined(__has_extension) -# if __has_extension(attribute_deprecated_with_message) +# if __has_extension(attribute_deprecated_with_message) # define DW_DEPRECATED(func, message) func __attribute__ ((deprecated (message))) # else # define DW_DEPRECATED(func, message) func __attribute__ ((deprecated)) # endif /* GCC */ #elif defined(__GNUC__) -# if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40500 +# if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40500 # define DW_DEPRECATED(func, message) func __attribute__ ((deprecated (message))) # else # define DW_DEPRECATED(func, message) func __attribute__ ((deprecated)) @@ -1568,6 +1648,7 @@ void API dw_mle_set_visible(HWND handle, int line); void API dw_mle_set_editable(HWND handle, int state); void API dw_mle_set_word_wrap(HWND handle, int state); +void API dw_mle_set_auto_complete(HWND handle, int state); int API dw_mle_search(HWND handle, char *text, int point, unsigned long flags); void API dw_spinbutton_set_pos(HWND handle, long position); void API dw_spinbutton_set_limits(HWND handle, long upper, long lower); @@ -1598,8 +1679,8 @@ void API dw_container_set_column_width(HWND handle, int column, int width); void API dw_container_set_row_title(void *pointer, int row, char *title); void API dw_container_change_row_title(HWND handle, int row, char *title); -#define dw_container_set_row_data(a, b, c) dw_container_set_row_title(a, b, (char *)c) -#define dw_container_change_row_data(a, b, c) dw_container_change_row_title(a, b, (char *)c) +void API dw_container_set_row_data(void *pointer, int row, void *data); +void API dw_container_change_row_data(HWND handle, int row, void *data); void API dw_container_insert(HWND handle, void *pointer, int rowcount); void API dw_container_clear(HWND handle, int redraw); void API dw_container_delete(HWND handle, int rowcount); @@ -1607,7 +1688,9 @@ char * API dw_container_query_next(HWND handle, unsigned long flags); void API dw_container_scroll(HWND handle, int direction, long rows); void API dw_container_cursor(HWND handle, char *text); +void API dw_container_cursor_by_data(HWND handle, void *data); void API dw_container_delete_row(HWND handle, char *text); +void API dw_container_delete_row_by_data(HWND handle, void *data); void API dw_container_optimize(HWND handle); void API dw_container_set_stripe(HWND handle, unsigned long oddcolor, unsigned long evencolor); void API dw_filesystem_set_column_title(HWND handle, char *title); @@ -1660,6 +1743,7 @@ void API dw_thread_end(void); DWTID API dw_thread_id(void); void API dw_exit(int exitcode); +void API dw_shutdown(void); HWND API dw_render_new(unsigned long id); void API dw_color_foreground_set(unsigned long value); void API dw_color_background_set(unsigned long value); @@ -1703,6 +1787,7 @@ int API dw_timer_connect(int interval, void *sigfunc, void *data); void API dw_timer_disconnect(int id); void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data); +void API dw_signal_connect_data(HWND window, char *signame, void *sigfunc, void *discfunc, void *data); void API dw_signal_disconnect_by_window(HWND window); void API dw_signal_disconnect_by_data(HWND window, void *data); void API dw_signal_disconnect_by_name(HWND window, char *signame); @@ -1729,5 +1814,8 @@ void API dw_print_cancel(HPRINT print); wchar_t * API dw_utf8_to_wchar(char *utf8string); char * API dw_wchar_to_utf8(wchar_t *wstring); +/* Exported for language bindings */ +void API _dw_init_thread(void); +void API _dw_deinit_thread(void); #endif
--- a/os2/dw.c Wed Sep 26 23:31:24 2012 -0500 +++ b/os2/dw.c Thu Sep 26 17:40:21 2019 -0500 @@ -2,7 +2,7 @@ * Dynamic Windows: * A GTK like implementation of the PM GUI * - * (C) 2000-2012 Brian Smith <brian@dbsoft.org> + * (C) 2000-2019 Brian Smith <brian@dbsoft.org> * (C) 2003-2011 Mark Hessling <mark@rexx.org> * (C) 2000 Achim Hasenmueller <achimha@innotek.de> * (C) 2000 Peter Nielsen <peter@pmview.com> @@ -65,7 +65,7 @@ MRESULT EXPENTRY _scrollwndproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2); void _do_resize(Box *thisbox, int x, int y); void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y); -int _load_bitmap_file(char *file, HWND handle, HBITMAP *hbm, HDC *hdc, HPS *hps, unsigned long *width, unsigned long *height, int *depth); +int _load_bitmap_file(char *file, HWND handle, HBITMAP *hbm, HDC *hdc, HPS *hps, unsigned long *width, unsigned long *height, int *depth, unsigned long backrgb); void _free_menu_data(HWND menu); BOOL (API_FUNC _WinQueryDesktopWorkArea)(HWND hwndDesktop, PWRECT pwrcWorkArea) = 0; /* PMPrintf support for dw_debug() */ @@ -166,6 +166,7 @@ HWND window; int id; void *signalfunction; + void *discfunction; void *data; } SignalHandler; @@ -216,7 +217,7 @@ /* This function adds a signal handler callback into the linked list. */ -void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data) +void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *discfunc, void *data) { SignalHandler *new = malloc(sizeof(SignalHandler)); @@ -224,6 +225,7 @@ new->window = window; new->id = id; new->signalfunction = signalfunction; + new->discfunction = discfunc; new->data = data; new->next = NULL; @@ -431,6 +433,14 @@ HPIXMAP disable = (HPIXMAP)dw_window_get_data(handle, "_dw_hpixmap_disabled"); HPOINTER icon = (HPOINTER)dw_window_get_data(handle, "_dw_button_icon"); + /* For safety purposes, reset all the window data */ + dw_window_set_data(handle, "_dw_bitmap", NULL); + dw_window_set_data(handle, "_dw_hps", NULL); + dw_window_set_data(handle, "_dw_hdc", NULL); + dw_window_set_data(handle, "_dw_hpixmap", NULL); + dw_window_set_data(handle, "_dw_hpixmap_disabled", NULL); + dw_window_set_data(handle, "_dw_button_icon", NULL); + if(icon) WinDestroyPointer(icon); @@ -610,14 +620,46 @@ strncmp(tmpbuf, "#37", 4)==0 || /* Container */ strncmp(tmpbuf, "#38", 4)== 0) /* Slider */ return 1; + if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */ + return 2; return 0; } -int _focus_check_box(Box *box, HWND handle, int start, HWND defaultitem) +#define _DW_DIRECTION_FORWARD -1 +#define _DW_DIRECTION_BACKWARD 1 + +int _focus_check_box(Box *box, HWND handle, int start, int direction, HWND defaultitem); + +/* Internal comparision function */ +int _focus_comp(int direction, int z, int end) +{ + if(direction == _DW_DIRECTION_FORWARD) + return z > -1; + return z < end; +} +int _focus_notebook(HWND hwnd, HWND handle, int start, int direction, HWND defaultitem) +{ + Box *notebox; + HWND page = (HWND)WinSendMsg(hwnd, BKM_QUERYPAGEWINDOWHWND, + (MPARAM)dw_notebook_page_get(hwnd), 0); + + if(page) + { + notebox = (Box *)WinQueryWindowPtr(page, QWP_USER); + + if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0, direction, defaultitem)) + return 1; + } + return 0; +} + +int _focus_check_box(Box *box, HWND handle, int start, int direction, HWND defaultitem) { int z; static HWND lasthwnd, firsthwnd; static int finish_searching; + int beg = (direction == _DW_DIRECTION_FORWARD) ? box->count-1 : 0; + int end = (direction == _DW_DIRECTION_FORWARD) ? -1 : box->count; /* Start is 2 when we have cycled completely and * need to set the focus to the last widget we found @@ -641,17 +683,22 @@ firsthwnd = 0; } - for(z=box->count-1;z>-1;z--) + for(z=beg;_focus_comp(direction, z, end);z+=direction) { if(box->items[z].type == TYPEBOX) { Box *thisbox = WinQueryWindowPtr(box->items[z].hwnd, QWP_USER); - if(thisbox && _focus_check_box(thisbox, handle, start == 3 ? 3 : 0, defaultitem)) + if(thisbox && _focus_check_box(thisbox, handle, start == 3 ? 3 : 0, direction, defaultitem)) return 1; } else { + int type = _validate_focus(box->items[z].hwnd); + + /* Special case notebook, can focus and contains items */ + if(type == 2 && direction == _DW_DIRECTION_FORWARD && _focus_notebook(box->items[z].hwnd, handle, start, direction, defaultitem)) + return 1; if(box->items[z].hwnd == handle) { if(lasthwnd == handle && firsthwnd) @@ -681,10 +728,10 @@ } } + lasthwnd = box->items[z].hwnd; + if(!firsthwnd) - firsthwnd = box->items[z].hwnd; - - lasthwnd = box->items[z].hwnd; + firsthwnd = lasthwnd; } else { @@ -694,38 +741,24 @@ if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0) { /* Then try the bottom or right box */ - HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_bottomright"); - - if(mybox) - { - Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER); - - if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - - /* Try the top or left box */ - mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_topleft"); + HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, (direction == _DW_DIRECTION_FORWARD) ? "_dw_bottomright" : "_dw_topleft"); if(mybox) { Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER); - if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem)) + if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, direction, defaultitem)) return 1; } - } - else if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */ - { - Box *notebox; - HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND, - (MPARAM)dw_notebook_page_get(box->items[z].hwnd), 0); - - if(page) + + /* Try the top or left box */ + mybox = (HWND)dw_window_get_data(box->items[z].hwnd, (direction == _DW_DIRECTION_FORWARD) ? "_dw_topleft" : "_dw_bottomright"); + + if(mybox) { - notebox = (Box *)WinQueryWindowPtr(page, QWP_USER); - - if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0, defaultitem)) + Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER); + + if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, direction, defaultitem)) return 1; } } @@ -738,147 +771,15 @@ { Box *scrollbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER); - if(scrollbox && _focus_check_box(scrollbox, handle, start == 3 ? 3 : 0, defaultitem)) + if(scrollbox && _focus_check_box(scrollbox, handle, start == 3 ? 3 : 0, direction, defaultitem)) return 1; } } } - } - } - return 0; -} - -int _focus_check_box_back(Box *box, HWND handle, int start, HWND defaultitem) -{ - int z; - static HWND lasthwnd, firsthwnd; - static int finish_searching; - - /* Start is 2 when we have cycled completely and - * need to set the focus to the last widget we found - * that was valid. - */ - if(start == 2) - { - if(lasthwnd) - WinSetFocus(HWND_DESKTOP, lasthwnd); - return 0; - } - - /* Start is 1 when we are entering the function - * for the first time, it is zero when entering - * the function recursively. - */ - if(start == 1) - { - lasthwnd = handle; - finish_searching = 0; - firsthwnd = 0; - } - - for(z=0;z<box->count;z++) - { - if(box->items[z].type == TYPEBOX) - { - Box *thisbox = WinQueryWindowPtr(box->items[z].hwnd, QWP_USER); - - if(thisbox && _focus_check_box_back(thisbox, handle, start == 3 ? 3 : 0, defaultitem)) + /* Special case notebook, can focus and contains items */ + if(type == 2 && direction == _DW_DIRECTION_BACKWARD && _focus_notebook(box->items[z].hwnd, handle, start, direction, defaultitem)) return 1; } - else - { - if(box->items[z].hwnd == handle) - { - if(lasthwnd == handle && firsthwnd) - WinSetFocus(HWND_DESKTOP, firsthwnd); - else if(lasthwnd == handle && !firsthwnd) - finish_searching = 1; - else - WinSetFocus(HWND_DESKTOP, lasthwnd); - - /* If we aren't looking for the last handle, - * return immediately. - */ - if(!finish_searching) - return 1; - } - if(_validate_focus(box->items[z].hwnd)) - { - /* Start is 3 when we are looking for the - * first valid item in the layout. - */ - if(start == 3) - { - if(!defaultitem || (defaultitem && defaultitem == box->items[z].hwnd)) - { - WinSetFocus(HWND_DESKTOP, box->items[z].hwnd); - return 1; - } - } - - if(!firsthwnd) - firsthwnd = box->items[z].hwnd; - - lasthwnd = box->items[z].hwnd; - } - else - { - char tmpbuf[100] = {0}; - - WinQueryClassName(box->items[z].hwnd, 99, (PCH)tmpbuf); - if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0) - { - /* Try the top or left box */ - HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_topleft"); - - if(mybox) - { - Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER); - - if(splitbox && _focus_check_box_back(splitbox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - - /* Then try the bottom or right box */ - mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_bottomright"); - - if(mybox) - { - Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER); - - if(splitbox && _focus_check_box_back(splitbox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - } - else if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */ - { - Box *notebox; - HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND, - (MPARAM)dw_notebook_page_get(box->items[z].hwnd), 0); - - if(page) - { - notebox = (Box *)WinQueryWindowPtr(page, QWP_USER); - - if(notebox && _focus_check_box_back(notebox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - } - else if(strncmp(tmpbuf, ScrollClassName, strlen(ScrollClassName)+1)==0) /* Scrollbox */ - { - /* Get the box window handle */ - HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_box"); - - if(mybox) - { - Box *scrollbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER); - - if(scrollbox && _focus_check_box_back(scrollbox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - } - } - } } return 0; } @@ -898,14 +799,14 @@ return 1; if(thisbox) - _focus_check_box(thisbox, handle, 3, thisbox->defaultitem); + _focus_check_box(thisbox, handle, 3, _DW_DIRECTION_FORWARD, thisbox->defaultitem); return 0; } /* This function finds the current widget in the * layout and moves the current focus to the next item. */ -void _shift_focus(HWND handle) +void _shift_focus(HWND handle, int direction) { Box *thisbox; HWND box, lastbox = _toplevel_window(handle); @@ -918,29 +819,8 @@ if(thisbox) { - if(_focus_check_box(thisbox, handle, 1, 0) == 0) - _focus_check_box(thisbox, handle, 2, 0); - } -} - -/* This function finds the current widget in the - * layout and moves the current focus to the next item. - */ -void _shift_focus_back(HWND handle) -{ - Box *thisbox; - HWND box, lastbox = _toplevel_window(handle); - - box = WinWindowFromID(lastbox, FID_CLIENT); - if(box) - thisbox = WinQueryWindowPtr(box, QWP_USER); - else - thisbox = WinQueryWindowPtr(lastbox, QWP_USER); - - if(thisbox) - { - if(_focus_check_box_back(thisbox, handle, 1, 0) == 0) - _focus_check_box_back(thisbox, handle, 2, 0); + if(_focus_check_box(thisbox, handle, 1, direction, 0) == 0) + _focus_check_box(thisbox, handle, 2, direction, 0); } } @@ -2615,9 +2495,9 @@ if(SHORT1FROMMP(mp2) == '\t') { if(CHARMSG(&msg)->fs & KC_SHIFT) - _shift_focus_back(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_BACKWARD); else - _shift_focus(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_FORWARD); return FALSE; } else if(SHORT1FROMMP(mp2) == '\r' && blah && blah->clickdefault) @@ -2869,9 +2749,9 @@ if(SHORT1FROMMP(mp2) == '\t') { if(CHARMSG(&msg)->fs & KC_SHIFT) - _shift_focus_back(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_BACKWARD); else - _shift_focus(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_FORWARD); return FALSE; } else if(SHORT1FROMMP(mp2) == '\r' && blah && blah->clickdefault) @@ -3282,8 +3162,9 @@ { case CN_ENTER: { - int (API_FUNC containerselectfunc)(HWND, char *, void *) = (int (API_FUNC)(HWND, char *, void *))tmp->signalfunction; + int (API_FUNC containerselectfunc)(HWND, char *, void *, void *) = (int (API_FUNC)(HWND, char *, void *, void *))tmp->signalfunction; char *text = NULL; + void *data = NULL; if(mp2) { @@ -3291,12 +3172,15 @@ pre = ((PNOTIFYRECORDENTER)mp2)->pRecord; if(pre) - text = (char *)pre->pszIcon; + { + text = (char *)pre->pszIcon; + data = (void *)pre->pszText; + } } if(tmp->window == notifyhwnd) { - result = containerselectfunc(tmp->window, text, tmp->data); + result = containerselectfunc(tmp->window, text, tmp->data, data); tmp = NULL; } } @@ -3375,14 +3259,16 @@ { if(tmp->window == pre->hwndCnr) { + /* PCNRITEM for Tree PRECORDCORE for Container */ PCNRITEM pci = (PCNRITEM)pre->pRecord; + PRECORDCORE prc = pre->pRecord; if(pci && pre->fEmphasisMask & CRA_CURSORED && (pci->rc.flRecordAttr & CRA_CURSORED)) { int (API_FUNC treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = (int (API_FUNC)(HWND, HTREEITEM, char *, void *, void *))tmp->signalfunction; if(dw_window_get_data(tmp->window, "_dw_container")) - result = treeselectfunc(tmp->window, 0, (char *)pci->rc.pszIcon, tmp->data, 0); + result = treeselectfunc(tmp->window, 0, (char *)prc->pszIcon, tmp->data, (void *)prc->pszText); else { if(lasthcnr == tmp->window && lastitem == (HWND)pci) @@ -3825,9 +3711,9 @@ if(SHORT1FROMMP(mp2) == '\t') { if(CHARMSG(&msg)->fs & KC_SHIFT) - _shift_focus_back(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_BACKWARD); else - _shift_focus(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_FORWARD); return FALSE; } break; @@ -4292,20 +4178,20 @@ if(SHORT1FROMMP(mp2) == '\t') { if(CHARMSG(&msg)->fs & KC_SHIFT) - _shift_focus_back(hwnd); + _shift_focus(hwnd, _DW_DIRECTION_BACKWARD); else - _shift_focus(hwnd); + _shift_focus(hwnd, _DW_DIRECTION_FORWARD); WinSendMsg(hwnd, BM_SETDEFAULT, 0, 0); return FALSE; } else if(!(CHARMSG(&msg)->fs & KC_KEYUP) && (CHARMSG(&msg)->vkey == VK_LEFT || CHARMSG(&msg)->vkey == VK_UP)) { - _shift_focus_back(hwnd); + _shift_focus(hwnd, _DW_DIRECTION_BACKWARD); return FALSE; } else if(!(CHARMSG(&msg)->fs & KC_KEYUP) && (CHARMSG(&msg)->vkey == VK_RIGHT || CHARMSG(&msg)->vkey == VK_DOWN)) { - _shift_focus(hwnd); + _shift_focus(hwnd, _DW_DIRECTION_FORWARD); return FALSE; } } @@ -4391,9 +4277,9 @@ if(SHORT1FROMMP(mp2) == '\t') { if(CHARMSG(&msg)->fs & KC_SHIFT) - _shift_focus_back(hwnd); + _shift_focus(hwnd, _DW_DIRECTION_BACKWARD); else - _shift_focus(hwnd); + _shift_focus(hwnd, _DW_DIRECTION_FORWARD); return FALSE; } break; @@ -4407,6 +4293,45 @@ return WinDefWindowProc(hwnd, msg, mp1, mp2); } +MRESULT EXPENTRY _NotebookProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + WindowData *blah = (WindowData *)WinQueryWindowPtr(hwnd, QWP_USER); + PFNWP oldproc = 0; + + if(blah) + oldproc = blah->oldproc; + + switch(msg) + { + case WM_PAINT: + if(!WinSendMsg(hwnd, BKM_QUERYPAGECOUNT, 0, (MPARAM)BKA_END)) + { + HPS hpsPaint; + RECTL rclPaint; + + hpsPaint = WinBeginPaint(hwnd, 0, &rclPaint); + WinFillRect(hpsPaint, &rclPaint, CLR_PALEGRAY); + WinEndPaint(hpsPaint); + } + break; + case WM_CHAR: + if(SHORT1FROMMP(mp2) == '\t') + { + if(CHARMSG(&msg)->fs & KC_SHIFT) + _shift_focus(hwnd, _DW_DIRECTION_BACKWARD); + else + _shift_focus(hwnd, _DW_DIRECTION_FORWARD); + return FALSE; + } + break; + } + + if(oldproc) + return oldproc(hwnd, msg, mp1, mp2); + + return WinDefWindowProc(hwnd, msg, mp1, mp2); +} + #ifdef UNICODE /* Internal function to detect the active keyboard layout */ UniChar *_detect_keyb(void) @@ -4712,6 +4637,9 @@ QMSG qmsg; void *tmp; + if(!dialog) + return NULL; + while (WinGetMsg(dwhab, &qmsg, 0, 0, 0)) { if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) @@ -6007,6 +5935,7 @@ { ULONG flags; HWND tmp; + WindowData *blah = calloc(1, sizeof(WindowData)); if(top) flags = BKS_MAJORTABTOP; @@ -6035,6 +5964,8 @@ WinSendMsg(tmp, BKM_SETDIMENSIONS,MPFROM2SHORT(102, 28), MPFROMSHORT( BKA_MAJORTAB)); } + blah->oldproc = WinSubclassWindow(tmp, _NotebookProc); + WinSetWindowPtr(tmp, QWP_USER, blah); dw_window_set_font(tmp, DefaultFont); return tmp; } @@ -6743,6 +6674,29 @@ return tmp; } +/* Internal function to create a disabled version of a pixmap */ +HPIXMAP _create_disabled(HWND handle, HPIXMAP pixmap) +{ + /* Create a disabled style pixmap */ + HPIXMAP disabled = dw_pixmap_new(handle, pixmap->width, pixmap->height, dw_color_depth_get()); + LONG fore = _foreground; + int z, j, lim; + + dw_pixmap_bitblt(0, disabled, 0, 0, pixmap->width, pixmap->height, 0, pixmap, 0, 0); + + dw_color_foreground_set(DW_CLR_PALEGRAY); + lim = pixmap->width/2; + for(j=0;j<pixmap->height;j++) + { + int mod = j%2; + + for(z=0;z<lim;z++) + dw_draw_point(0, disabled, (z*2)+mod, j); + } + _foreground = fore; + return disabled; +} + /* * Create a new bitmap button window (widget) to be packed from a file. * Parameters: @@ -6772,8 +6726,7 @@ if(file && (pixmap = calloc(1,sizeof(struct _hpixmap)))) { - int z, j, lim, len; - LONG fore; + int z, len; strcpy(file, filename); @@ -6786,7 +6739,7 @@ if(stricmp(file + len - 4, ".ico") == 0) icon = WinLoadFileIcon((PSZ)file, FALSE); else - _load_bitmap_file(file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height, &pixmap->depth); + _load_bitmap_file(file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height, &pixmap->depth, DW_CLR_DEFAULT); } } else @@ -6802,7 +6755,7 @@ strcpy(file, filename); strcat(file, image_exts[z]); if(access(file, 04) == 0 && - _load_bitmap_file(file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height, &pixmap->depth)) + _load_bitmap_file(file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height, &pixmap->depth, DW_CLR_DEFAULT)) break; } } @@ -6815,21 +6768,7 @@ } else { - /* Create a disabled style pixmap */ - disabled = dw_pixmap_new(tmp, pixmap->width, pixmap->height, dw_color_depth_get()); - dw_pixmap_bitblt(0, disabled, 0, 0, pixmap->width, pixmap->height, 0, pixmap, 0, 0); - - fore = _foreground; - dw_color_foreground_set(DW_CLR_PALEGRAY); - lim = pixmap->width/2; - for(j=0;j<pixmap->height;j++) - { - int mod = j%2; - - for(z=0;z<lim;z++) - dw_draw_point(0, disabled, (z*2)+mod, j); - } - _foreground = fore; + disabled = _create_disabled(tmp, pixmap); } } @@ -6880,8 +6819,6 @@ if((pixmap = calloc(1, sizeof(struct _hpixmap))) != NULL) { - int z, j, lim; - LONG fore; file = tmpnam( NULL ); if ( file != NULL ) { @@ -6890,7 +6827,7 @@ { fwrite( data, 1, len, fp ); fclose( fp ); - if(!_load_bitmap_file( file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height, &pixmap->depth)) + if(!_load_bitmap_file( file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height, &pixmap->depth, DW_CLR_DEFAULT)) { icon = WinLoadFileIcon((PSZ)file, FALSE); } @@ -6910,21 +6847,7 @@ } else { - /* Create a disabled style pixmap */ - disabled = dw_pixmap_new(tmp, pixmap->width, pixmap->height, dw_color_depth_get()); - dw_pixmap_bitblt(0, disabled, 0, 0, pixmap->width, pixmap->height, 0, pixmap, 0, 0); - - fore = _foreground; - dw_color_foreground_set(DW_CLR_PALEGRAY); - lim = pixmap->width/2; - for(j=0;j<pixmap->height;j++) - { - int mod = j%2; - - for(z=0;z<lim;z++) - dw_draw_point(0, disabled, (z*2)+mod, j); - } - _foreground = fore; + disabled = _create_disabled(tmp, pixmap); } } @@ -7151,6 +7074,94 @@ WinSendMsg(handle, WM_SETICON, (MPARAM)hptr, 0); } +/* Code from GBM to convert to 24bpp if it isn't currently */ +static int _To24Bit(GBM *gbm, GBMRGB *gbmrgb, BYTE **ppbData) +{ + unsigned long stride = (((unsigned long)gbm -> w * gbm -> bpp + 31)/32) * 4; + unsigned long new_stride = (((unsigned long)gbm -> w * 3 + 3) & ~3); + unsigned long bytes; + int y; + unsigned char *pbDataNew; + + if ( gbm -> bpp == 24 ) + { + return ( TRUE ); + } + + bytes = new_stride * gbm -> h; + /* Allocate a buffer to store the image */ + if(DosAllocMem((PPVOID)&pbDataNew, (ULONG)bytes, PAG_READ | PAG_WRITE | PAG_COMMIT) != NO_ERROR) + { + return ( FALSE ); + } + + for ( y = 0; y < gbm -> h; y++ ) + { + unsigned char *src = *ppbData + y * stride; + unsigned char *dest = pbDataNew + y * new_stride; + int x; + + switch ( gbm -> bpp ) + { + case 1: + { + unsigned char c = 0; + for ( x = 0; x < gbm -> w; x++ ) + { + if ( (x & 7) == 0 ) + c = *src++; + else + c <<= 1; + + *dest++ = gbmrgb [(c & 0x80) != 0].b; + *dest++ = gbmrgb [(c & 0x80) != 0].g; + *dest++ = gbmrgb [(c & 0x80) != 0].r; + } + } + break; + + case 4: + for ( x = 0; x + 1 < gbm -> w; x += 2 ) + { + unsigned char c = *src++; + + *dest++ = gbmrgb [c >> 4].b; + *dest++ = gbmrgb [c >> 4].g; + *dest++ = gbmrgb [c >> 4].r; + *dest++ = gbmrgb [c & 15].b; + *dest++ = gbmrgb [c & 15].g; + *dest++ = gbmrgb [c & 15].r; + } + + if ( x < gbm -> w ) + { + unsigned char c = *src; + + *dest++ = gbmrgb [c >> 4].b; + *dest++ = gbmrgb [c >> 4].g; + *dest++ = gbmrgb [c >> 4].r; + } + break; + + case 8: + for ( x = 0; x < gbm -> w; x++ ) + { + unsigned char c = *src++; + + *dest++ = gbmrgb [c].b; + *dest++ = gbmrgb [c].g; + *dest++ = gbmrgb [c].r; + } + break; + } + } + DosFreeMem(*ppbData); + *ppbData = pbDataNew; + gbm->bpp = 24; + + return ( TRUE ); +} + /* GBM seems to be compiled with VisualAge which defines O_BINARY and O_RDONLY * as follows... but other compilers (GCC and Watcom at least) define them * differently... so we add defines that are compatible with VAC here. @@ -7161,7 +7172,7 @@ /* Internal function to load a bitmap from a file and return handles * to the bitmap, presentation space etc. */ -int _load_bitmap_file(char *file, HWND handle, HBITMAP *hbm, HDC *hdc, HPS *hps, unsigned long *width, unsigned long *height, int *depth) +int _load_bitmap_file(char *file, HWND handle, HBITMAP *hbm, HDC *hdc, HPS *hps, unsigned long *width, unsigned long *height, int *depth, unsigned long backrgb) { PBITMAPINFOHEADER2 pBitmapInfoHeader; /* pointer to the first byte of bitmap data */ @@ -7176,7 +7187,7 @@ { int fd, z, err = -1, ft = 0; GBM gbm; - GBMRGB *gbmrgb; + GBMRGB *gbmrgb = NULL; ULONG byteswidth; /* Try to open the file */ @@ -7193,8 +7204,27 @@ for(z=0;z<ft;z++) { + /* Using CLR_PALEGRAY as a default alpha background... we can + * change this to use WinQuerySysColor() later, but pale gray is + * already hardcoded elsewhere so just continue using it here. + */ + char options[101] = "back_rgb=52224_52224_52224"; + + /* Ask the control if it has another color set */ + if(backrgb == DW_CLR_DEFAULT && handle) + { + RGB rgb = {0}; + + if(WinQueryPresParam(handle, PP_BACKGROUNDCOLOR, PP_BACKGROUNDCOLORINDEX, NULL, sizeof(rgb), &rgb, QPF_NOINHERIT | QPF_PURERGBCOLOR | QPF_ID2COLORINDEX)) + sprintf(options, "back_rgb=%d_%d_%d", rgb.bRed * 256, rgb.bGreen * 256, rgb.bBlue * 256); + } + else if(backrgb & DW_RGB_COLOR) + { + sprintf(options, "back_rgb=%d_%d_%d", (int)DW_RED_VALUE(backrgb) * 256, (int)DW_GREEN_VALUE(backrgb) * 256, (int)DW_BLUE_VALUE(backrgb) * 256); + } + /* Read the file header */ - if((err = _gbm_read_header(file, fd, z, &gbm, "")) == 0) + if((err = _gbm_read_header(file, fd, z, &gbm, options)) == 0) break; } @@ -7211,7 +7241,7 @@ /* if less than 24-bit, then have palette */ if(gbm.bpp < 24) { - gbmrgb = alloca(sizeof(GBMRGB)); + gbmrgb = alloca(sizeof(GBMRGB) * 256); /* Read the palette from the file */ if((err = _gbm_read_palette(fd, z, &gbm, gbmrgb)) != 0) { @@ -7222,8 +7252,6 @@ return 0; } } - else - gbmrgb = NULL; /* Save the dimension for return */ *width = gbm.w; @@ -7249,6 +7277,18 @@ /* Close the file */ _gbm_io_close(fd); + /* Convert to 24bpp for use in the application */ + if(_To24Bit(&gbm, gbmrgb, &BitmapFileBegin)) + *depth = 24; + else + { +#ifdef DEBUG + dw_debug("GBM: Failed 24bpp conversion \"%s\"\n", file); +#endif + DosFreeMem(BitmapFileBegin); + return 0; + } + pBitmapInfoHeader = alloca(sizeof(BITMAPINFOHEADER2)); memset(pBitmapInfoHeader, 0, sizeof(BITMAPINFOHEADER2)); pBitmapInfoHeader->cbFix = sizeof(BITMAPINFOHEADER2); @@ -7364,6 +7404,65 @@ return 1; } +/* Internal function to change the button bitmap */ +void _dw_window_set_bitmap(HWND handle, HBITMAP hbm, HDC hdc, HPS hps, unsigned long width, unsigned long height, int depth, HPOINTER icon) +{ + char tmpbuf[100] = {0}; + + WinQueryClassName(handle, 99, (PCH)tmpbuf); + + /* Button */ + if(strncmp(tmpbuf, "#3", 3)==0) + { + WNDPARAMS wp = {0}; + BTNCDATA bcd = {0}; + RECTL rect; + + wp.fsStatus = WPM_CTLDATA; + wp.pCtlData = &bcd; + wp.cbCtlData = bcd.cb = sizeof(BTNCDATA); + + /* Clear any existing icon */ + WinSendMsg(handle, WM_SETWINDOWPARAMS, (MPARAM)&wp, NULL); + + if(icon) + { + dw_window_set_data(handle, "_dw_button_icon", DW_POINTER(icon)); + } + else + { + HPIXMAP disabled, pixmap = calloc(1,sizeof(struct _hpixmap)); + + pixmap->hbm = hbm; + pixmap->hdc = hdc; + pixmap->hps = hps; + pixmap->width = width; + pixmap->height = height; + disabled = _create_disabled(handle, pixmap); + + dw_window_set_data(handle, "_dw_hpixmap", DW_POINTER(pixmap)); + dw_window_set_data(handle, "_dw_hpixmap_disabled", DW_POINTER(disabled)); + } + dw_window_set_data(handle, "_dw_bitmapbutton", DW_POINTER(1)); + /* Make sure we invalidate the button so it redraws */ + WinQueryWindowRect(handle, &rect); + WinInvalidateRect(handle, &rect, TRUE); + } + + /* If we changed the bitmap... */ + { + Item *item = _box_item(handle); + + /* Check to see if any of the sizes need to be recalculated */ + if(item && (item->origwidth == -1 || item->origheight == -1)) + { + _control_size(handle, item->origwidth == -1 ? &item->width : NULL, item->origheight == -1 ? &item->height : NULL); + /* Queue a redraw on the top-level window */ + _dw_redraw(_toplevel_window(handle), TRUE); + } + } +} + /* * Sets the bitmap used for a given static window. * Parameters: @@ -7376,8 +7475,12 @@ */ void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename) { - HBITMAP hbm; - HPS hps; + HBITMAP hbm = 0; + HPS hps = 0; + HDC hdc = 0; + HPOINTER icon = 0; + unsigned long width = 0, height = 0; + int depth = 0; /* Destroy any old bitmap data */ _free_bitmap(handle); @@ -7387,13 +7490,11 @@ { hps = WinGetPS( handle ); hbm = GpiLoadBitmap( hps, NULLHANDLE, id, 0, 0 ); + WinReleasePS(hps); } else if ( filename ) { - HDC hdc = 0; - unsigned long width, height; char *file = alloca(strlen(filename) + 6); - int depth; if(!file) return; @@ -7403,22 +7504,38 @@ /* check if we can read from this file (it exists and read permission) */ if(access(file, 04) != 0) { - int z; - - /* Try with supported extensions */ - for(z=0;z<(_gbm_init?NUM_EXTS:1);z++) - { - strcpy(file, filename); - strcat(file, image_exts[z]); - if(access(file, 04) == 0 && - _load_bitmap_file(file, handle, &hbm, &hdc, &hps, &width, &height, &depth)) - break; - } + /* Try with .ico extension first...*/ + strcat(file, ".ico"); + if(access(file, 04) == 0) + icon = WinLoadFileIcon((PSZ)file, FALSE); + else + { + int z; + + /* Try with supported extensions */ + for(z=0;z<(_gbm_init?NUM_EXTS:1);z++) + { + strcpy(file, filename); + strcat(file, image_exts[z]); + if(access(file, 04) == 0 && + _load_bitmap_file(file, handle, &hbm, &hdc, &hps, &width, &height, &depth, DW_CLR_DEFAULT)) + break; + } + } } else - _load_bitmap_file(file, handle, &hbm, &hdc, &hps, &width, &height, &depth); - - if(!hdc) + { + int len = strlen( file ); + if(len > 4) + { + if(stricmp(file + len - 4, ".ico") == 0) + icon = WinLoadFileIcon((PSZ)file, FALSE); + else + _load_bitmap_file(file, handle, &hbm, &hdc, &hps, &width, &height, &depth, DW_CLR_DEFAULT); + } + } + + if(!hdc && !icon) return; dw_window_set_data(handle, "_dw_hps", (void *)hps); @@ -7429,22 +7546,9 @@ else return; - if ( id ) - WinReleasePS(hps); dw_window_set_data(handle, "_dw_bitmap", (void *)hbm); - - /* If we changed the bitmap... */ - { - Item *item = _box_item(handle); - - /* Check to see if any of the sizes need to be recalculated */ - if(item && (item->origwidth == -1 || item->origheight == -1)) - { - _control_size(handle, item->origwidth == -1 ? &item->width : NULL, item->origheight == -1 ? &item->height : NULL); - /* Queue a redraw on the top-level window */ - _dw_redraw(_toplevel_window(handle), TRUE); - } - } + + _dw_window_set_bitmap(handle, hbm, hdc, hps, width, height, depth, icon); } /* @@ -7480,7 +7584,7 @@ { fwrite( data, 1, len, fp ); fclose( fp ); - if(!_load_bitmap_file(file, handle, &hbm, &hdc, &hps, &width, &height, &depth)) + if(!_load_bitmap_file(file, handle, &hbm, &hdc, &hps, &width, &height, &depth, DW_CLR_DEFAULT)) { /* can't use ICO ? */ unlink( file ); @@ -7505,13 +7609,14 @@ { hps = WinGetPS( handle ); hbm = GpiLoadBitmap( hps, NULLHANDLE, id, 0, 0 ); + WinReleasePS(hps); } else return; - if ( id ) - WinReleasePS(hps); dw_window_set_data(handle, "_dw_bitmap", (void *)hbm); + + _dw_window_set_bitmap(handle, hbm, hdc, hps, width, height, depth, 0); } /* @@ -8284,8 +8389,12 @@ */ unsigned long API dw_notebook_page_new(HWND handle, ULONG flags, int front) { - return (ULONG)WinSendMsg(handle, BKM_INSERTPAGE, 0L, - MPFROM2SHORT((BKA_STATUSTEXTON | BKA_AUTOPAGESIZE | BKA_MAJOR | flags), front ? BKA_FIRST : BKA_LAST)); + ULONG retval = (ULONG)WinSendMsg(handle, BKM_INSERTPAGE, 0L, + MPFROM2SHORT((BKA_STATUSTEXTON | BKA_AUTOPAGESIZE | BKA_MAJOR | flags), front ? BKA_FIRST : BKA_LAST)); + RECTL rect; + WinQueryWindowRect(handle, &rect); + WinInvalidateRect(handle, &rect, TRUE); + return retval; } /* @@ -8298,10 +8407,13 @@ { HWND pagehwnd = (HWND)WinSendMsg(handle, BKM_QUERYPAGEWINDOWHWND, MPFROMLONG(pageid), 0L); + RECTL rect; WinSendMsg(handle, BKM_DELETEPAGE, MPFROMLONG(pageid), (MPARAM)BKA_SINGLE); if(pagehwnd) dw_window_destroy(pagehwnd); + WinQueryWindowRect(handle, &rect); + WinInvalidateRect(handle, &rect, TRUE); } /* @@ -8704,6 +8816,16 @@ } /* + * Sets the word auto complete state of an MLE box. + * Parameters: + * handle: Handle to the MLE. + * state: Bitwise combination of DW_MLE_COMPLETE_TEXT/DASH/QUOTE + */ +void API dw_mle_set_auto_complete(HWND handle, int state) +{ +} + +/* * Sets the current cursor position of an MLE box. * Parameters: * handle: Handle to the MLE to be positioned. @@ -9073,8 +9195,8 @@ PCNRITEM pci = (PCNRITEM)item; handle = handle; /* keep compiler happy */ - if(pci) - return (char *)pci->rc.pszIcon; + if(pci && pci->rc.pszIcon) + return strdup((char *)pci->rc.pszIcon); return NULL; } @@ -9367,8 +9489,35 @@ return WinLoadPointer(HWND_DESKTOP,module,id); } +#if 0 +/* Internal function to create pointer/icon masks */ +void _create_mask(HPIXMAP src, HPIXMAP mask, unsigned long backrgb) +{ + LONG maskcolor = (DW_RED_VALUE(backrgb) << 16) | (DW_GREEN_VALUE(backrgb) << 8) | DW_BLUE_VALUE(backrgb); + int x, y; + + for(x=0; x < src->width; x++) + { + for(y=0; y < src->height; y++) + { + POINTL pt = {x, y}; + LONG color = GpiQueryPel(src->hps, &pt); + + dw_debug("Mask color %x (%dx%d) %x\n", (int)maskcolor, x, y, (int)color); + if(color == maskcolor) + { + GpiSetColor(mask->hps, CLR_WHITE); + GpiSetPel(mask->hps, &pt); + pt.y = y + src->height; + GpiSetPel(mask->hps, &pt); + } + } + } +} +#endif + /* Internal function to create an icon from an existing pixmap */ -HICN _create_icon(HPIXMAP src) +HICN _create_icon(HPIXMAP src, unsigned long backrgb) { HPIXMAP pntr = dw_pixmap_new(hwndApp, WinQuerySysValue(HWND_DESKTOP, SV_CXICON), WinQuerySysValue(HWND_DESKTOP, SV_CYICON), src->depth); HPIXMAP mask = dw_pixmap_new(hwndApp, pntr->width, pntr->height*2, 1); @@ -9385,6 +9534,14 @@ dw_color_foreground_set(DW_CLR_BLACK); dw_draw_rect(0, mask, DW_DRAW_FILL, 0, 0, mask->width, mask->height); dw_draw_rect(0, minimask, DW_DRAW_FILL, 0, 0, minimask->width, minimask->height); +#if 0 + /* If we have a background color... create masks */ + if(backrgb & DW_RGB_COLOR) + { + _create_mask(pntr, mask, backrgb); + _create_mask(minipntr, minimask, backrgb); + } +#endif _foreground = oldcol; /* Assemble the Pointer Info structure */ @@ -9393,7 +9550,7 @@ pi.hbmMiniPointer = minimask->hbm; pi.hbmMiniColor = minipntr->hbm; - /* Destroy the pixmaps but not the bitmaps */ + /* Destroy the temporary pixmaps */ mask->hbm = pntr->hbm = minimask->hbm = minipntr->hbm = 0; dw_pixmap_destroy(mask); dw_pixmap_destroy(pntr); @@ -9416,6 +9573,7 @@ char *file = alloca(strlen(filename) + 6); HPIXMAP src = alloca(sizeof(struct _hpixmap)); HICN icon = 0; + unsigned long defcol = DW_RGB(204, 204, 204); if(!file || !src) return 0; @@ -9438,15 +9596,15 @@ strcpy(file, filename); strcat(file, image_exts[z]); if(access(file, 04) == 0 && - _load_bitmap_file(file, hwndApp, &src->hbm, &src->hdc, &src->hps, &src->width, &src->height, &src->depth)) + _load_bitmap_file(file, hwndApp, &src->hbm, &src->hdc, &src->hps, &src->width, &src->height, &src->depth, defcol)) { - icon = _create_icon(src); + icon = _create_icon(src, defcol); break; } } } - else if(_load_bitmap_file(file, hwndApp, &src->hbm, &src->hdc, &src->hps, &src->width, &src->height, &src->depth)) - icon = _create_icon(src); + else if(_load_bitmap_file(file, hwndApp, &src->hbm, &src->hdc, &src->hps, &src->width, &src->height, &src->depth, defcol)) + icon = _create_icon(src, defcol); /* Free temporary resources if in use */ if(icon) { @@ -9647,13 +9805,19 @@ WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); ULONG totalsize, size = 0, *flags = blah ? blah->data : 0; int z, count = 0; - + char *oldtitle = (char *)temp->pszIcon; + if(!flags) return; while(flags[count]) count++; + /* Empty and free the title memory */ + temp->pszIcon = temp->pszText = NULL; + if(oldtitle) + free(oldtitle); + /* Figure out the offsets to the items in the struct */ for(z=0;z<count;z++) { @@ -9867,6 +10031,7 @@ PRECORDCORE temp; int z, currentcount; CNRINFO cnr; + char *newtitle; if(!ci) return; @@ -9883,9 +10048,8 @@ for(z=0;z<(row-currentcount);z++) temp = temp->preccNextRecord; - temp->pszIcon = (PSZ)title; - temp->pszName = (PSZ)title; - temp->pszText = (PSZ)title; + newtitle = title ? strdup(title) : NULL; + temp->pszName = temp->pszIcon = (PSZ)newtitle; } /* @@ -9904,9 +10068,70 @@ { if(count == row) { - pCore->pszIcon = (PSZ)title; - pCore->pszName = (PSZ)title; - pCore->pszText = (PSZ)title; + char *oldtitle = (char *)pCore->pszIcon; + char *newtitle = title ? strdup(title) : NULL; + pCore->pszName = pCore->pszIcon = (PSZ)newtitle; + + WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_NOREPOSITION | CMA_TEXTCHANGED)); + + if(oldtitle) + free(oldtitle); + return; + } + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + count++; + } +} + +/* + * Sets the data of a row in the container. + * Parameters: + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * row: Zero based row of data being set. + * data: Data pointer. + */ +void API dw_container_set_row_data(void *pointer, int row, void *data) +{ + ContainerInfo *ci = (ContainerInfo *)pointer; + PRECORDCORE temp; + int z, currentcount; + CNRINFO cnr; + + if(!ci) + return; + + temp = (PRECORDCORE)ci->data; + + z = 0; + + if(!_dw_send_msg(ci->handle, CM_QUERYCNRINFO, (MPARAM)&cnr, MPFROMSHORT(sizeof(CNRINFO)), 0)) + return; + + currentcount = cnr.cRecords; + + for(z=0;z<(row-currentcount);z++) + temp = temp->preccNextRecord; + + temp->pszText = (PSZ)data; +} + +/* + * Changes the data of a row already inserted in the container. + * Parameters: + * handle: Handle to the container window (widget). + * row: Zero based row of data being set. + * data: Data pointer. + */ +void API dw_container_change_row_data(HWND handle, int row, void *data) +{ + PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); + int count = 0; + + while(pCore) + { + if(count == row) + { + pCore->pszText = (PSZ)data; WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_NOREPOSITION | CMA_TEXTCHANGED)); return; @@ -10076,7 +10301,9 @@ if(pCore->flRecordAttr & flags) { dw_window_set_data(handle, "_dw_pcore", (void *)pCore); - return (char *)pCore->pszIcon; + if(flags & DW_CR_RETDATA) + return (char *)pCore->pszText; + return pCore->pszIcon ? strdup((char *)pCore->pszIcon) : NULL; } pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); } @@ -10084,7 +10311,9 @@ else { dw_window_set_data(handle, "_dw_pcore", (void *)pCore); - return (char *)pCore->pszIcon; + if(flags & DW_CR_RETDATA) + return (char *)pCore->pszText; + return pCore->pszIcon ? strdup((char *)pCore->pszIcon) : NULL; } } return NULL; @@ -10113,7 +10342,9 @@ if(pCore->flRecordAttr & flags) { dw_window_set_data(handle, "_dw_pcore", (void *)pCore); - return (char *)pCore->pszIcon; + if(flags & DW_CR_RETDATA) + return (char *)pCore->pszText; + return pCore->pszIcon ? strdup((char *)pCore->pszIcon) : NULL; } pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); @@ -10122,7 +10353,9 @@ else { dw_window_set_data(handle, "_dw_pcore", (void *)pCore); - return (char *)pCore->pszIcon; + if(flags & DW_CR_RETDATA) + return (char *)pCore->pszText; + return pCore->pszIcon ? strdup((char *)pCore->pszIcon) : NULL; } } return NULL; @@ -10138,11 +10371,10 @@ { RECTL viewport, item; PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); - int textcomp = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_textcomp")); while(pCore) { - if((textcomp && pCore->pszIcon && strcmp((char *)pCore->pszIcon, text) == 0) || (!textcomp && (char *)pCore->pszIcon == text)) + if(pCore->pszIcon && strcmp((char *)pCore->pszIcon, text) == 0) { QUERYRECORDRECT qrr; int scrollpixels = 0, midway; @@ -10176,11 +10408,69 @@ void API dw_container_delete_row(HWND handle, char *text) { PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); - int textcomp = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_textcomp")); + + while(pCore) + { + if(pCore->pszIcon && strcmp((char *)pCore->pszIcon, text) == 0) + { + WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_FREE | CMA_INVALIDATE)); + return; + } + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + } +} + +/* + * Cursors the item with the data speficied, and scrolls to that item. + * Parameters: + * handle: Handle to the window (widget) to be queried. + * data: Data usually returned by dw_container_query(). + */ +void API dw_container_cursor_by_data(HWND handle, void *data) +{ + RECTL viewport, item; + PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); while(pCore) { - if((textcomp && pCore->pszIcon && strcmp((char *)pCore->pszIcon, text) == 0) || (!textcomp && (char *)pCore->pszIcon == text)) + if((void *)pCore->pszText == data) + { + QUERYRECORDRECT qrr; + int scrollpixels = 0, midway; + + qrr.cb = sizeof(QUERYRECORDRECT); + qrr.pRecord = pCore; + qrr.fRightSplitWindow = 0; + qrr.fsExtent = CMA_TEXT; + + WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)pCore, MPFROM2SHORT(TRUE, CRA_CURSORED)); + WinSendMsg(handle, CM_QUERYVIEWPORTRECT, (MPARAM)&viewport, MPFROM2SHORT(CMA_WORKSPACE, FALSE)); + WinSendMsg(handle, CM_QUERYRECORDRECT, (MPARAM)&item, (MPARAM)&qrr); + + midway = (viewport.yTop - viewport.yBottom)/2; + scrollpixels = viewport.yTop - (item.yTop + midway); + + WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(scrollpixels)); + return; + } + + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + } +} + +/* + * Deletes the item with the data speficied. + * Parameters: + * handle: Handle to the window (widget). + * data: Data usually returned by dw_container_query(). + */ +void API dw_container_delete_row_by_data(HWND handle, void *data) +{ + PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); + + while(pCore) + { + if((void *)pCore->pszText == data) { WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_FREE | CMA_INVALIDATE)); return; @@ -10965,7 +11255,7 @@ strcpy(file, filename); strcat(file, image_exts[z]); if(access(file, 04) == 0 && - _load_bitmap_file(file, handle, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height, &pixmap->depth)) + _load_bitmap_file(file, handle, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height, &pixmap->depth, DW_CLR_DEFAULT)) break; } } @@ -11011,7 +11301,7 @@ { fwrite( data, 1, len, fp ); fclose( fp ); - if(!_load_bitmap_file(file, handle, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height, &pixmap->depth)) + if(!_load_bitmap_file(file, handle, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height, &pixmap->depth, DW_CLR_DEFAULT)) { /* can't use ICO ? */ unlink( file ); @@ -11631,28 +11921,81 @@ return 0; } -/* - * Encapsulate the message queues on OS/2. - */ -void _dwthreadstart(void *data) +/* + * Generally an internal function called from a newly created + * thread to setup the Dynamic Windows environment for the thread. + * However it is exported so language bindings can call it when + * they create threads that require access to Dynamic Windows. + */ +void **_dw_init_thread2(void) { HAB thishab = WinInitialize(0); HMQ thishmq = WinCreateMsgQueue(thishab, 0); - void (API_FUNC threadfunc)(void *) = NULL; - void **tmp = (void **)data; + void **threadinfo = (void **)malloc(sizeof(void *) * 2); + + threadinfo[0] = (void *)thishab; + threadinfo[1] = (void *)thishmq; + +#ifndef __WATCOMC__ + *_threadstore() = (void *)threadinfo; +#endif #ifdef UNICODE /* Set the codepage to 1208 (UTF-8) */ WinSetCp(thishmq, 1208); #endif + return threadinfo; +} + +void API _dw_init_thread(void) +{ + _dw_init_thread2(); +} + +/* + * Generally an internal function called from a terminating + * thread to cleanup the Dynamic Windows environment for the thread. + * However it is exported so language bindings can call it when + * they exit threads that require access to Dynamic Windows. + */ +void _dw_deinit_thread2(void **threadinfo) +{ +#ifndef __WATCOMC__ + if(!threadinfo) + threadinfo = (void **)*_threadstore(); +#endif + + if(threadinfo) + { + HAB thishab = (HAB)threadinfo[0]; + HMQ thishmq = (HMQ)threadinfo[1]; + + WinDestroyMsgQueue(thishmq); + WinTerminate(thishab); + free(threadinfo); + } +} + +void API _dw_deinit_thread(void) +{ + _dw_deinit_thread2(NULL); +} + +/* + * Encapsulate the message queues on OS/2. + */ +void _dwthreadstart(void *data) +{ + void (API_FUNC threadfunc)(void *) = NULL; + void **tmp = (void **)data; + void **threadinfo = _dw_init_thread2(); threadfunc = (void (API_FUNC)(void *))tmp[0]; threadfunc(tmp[1]); free(tmp); - WinDestroyMsgQueue(thishmq); - WinTerminate(thishab); + _dw_deinit_thread2(threadinfo); } /* @@ -11684,6 +12027,7 @@ */ void API dw_thread_end(void) { + _dw_deinit_thread(); _endthread(); } @@ -11697,10 +12041,8 @@ /* * Cleanly terminates a DW session, should be signal handler safe. - * Parameters: - * exitcode: Exit code reported to the operating system. - */ -void API dw_exit(int exitcode) + */ +void API dw_shutdown(void) { /* Destroy the menu message window */ dw_window_destroy(hwndApp); @@ -11713,7 +12055,10 @@ /* Deinit the GBM */ if(_gbm_deinit) + { _gbm_deinit(); + _gbm_deinit = NULL; + } #ifdef UNICODE /* Free the conversion object */ @@ -11731,7 +12076,16 @@ DosFreeModule(pmprintf); DosFreeModule(pmmerge); DosFreeModule(gbm); - +} + +/* + * Cleanly terminates a DW session, should be signal handler safe. + * Parameters: + * exitcode: Exit code reported to the operating system. + */ +void API dw_exit(int exitcode) +{ + dw_shutdown(); /* And finally exit */ exit(exitcode); } @@ -13073,7 +13427,7 @@ if(timerid) { - _new_signal(WM_TIMER, NULLHANDLE, timerid, sigfunc, data); + _new_signal(WM_TIMER, NULLHANDLE, timerid, sigfunc, NULL, data); return timerid; } } @@ -13130,6 +13484,20 @@ */ void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data) { + dw_signal_connect_data(window, signame, sigfunc, NULL, data); +} + +/* + * Add a callback to a window event with a closure callback. + * Parameters: + * window: Window handle of signal to be called back. + * signame: A string pointer identifying which signal to be hooked. + * sigfunc: The pointer to the function to be used as the callback. + * discfunc: The pointer to the function called when this handler is removed. + * data: User data to be passed to the handler function. + */ +void API dw_signal_connect_data(HWND window, char *signame, void *sigfunc, void *discfunc, void *data) +{ ULONG message = 0, id = 0; if(window && signame && sigfunc) @@ -13154,7 +13522,7 @@ window = owner; } } - _new_signal(message, window, id, sigfunc, data); + _new_signal(message, window, id, sigfunc, discfunc, data); } } } @@ -13176,6 +13544,13 @@ { if(((window < 65536 && tmp->id == window) || tmp->window == window) && tmp->message == message) { + void (API_FUNC discfunc)(HWND, void *) = (void (API_FUNC)(HWND, void *))tmp->discfunction; + + if(discfunc) + { + discfunc(tmp->window, tmp->data); + } + if(prev) { prev->next = tmp->next; @@ -13210,6 +13585,13 @@ { if((window < 65536 && tmp->id == window) || tmp->window == window) { + void (API_FUNC discfunc)(HWND, void *) = (void (API_FUNC)(HWND, void *))tmp->discfunction; + + if(discfunc) + { + discfunc(tmp->window, tmp->data); + } + if(prev) { prev->next = tmp->next; @@ -13245,6 +13627,13 @@ { if(((window < 65536 && tmp->id == window) || tmp->window == window) && tmp->data == data) { + void (API_FUNC discfunc)(HWND, void *) = (void (API_FUNC)(HWND, void *))tmp->discfunction; + + if(discfunc) + { + discfunc(tmp->window, tmp->data); + } + if(prev) { prev->next = tmp->next;
--- a/win/dw.c Wed Sep 26 23:31:24 2012 -0500 +++ b/win/dw.c Thu Sep 26 17:40:21 2019 -0500 @@ -2,7 +2,7 @@ * Dynamic Windows: * A GTK like implementation of the Win32 GUI * - * (C) 2000-2012 Brian Smith <brian@dbsoft.org> + * (C) 2000-2019 Brian Smith <brian@dbsoft.org> * (C) 2003-2011 Mark Hessling <mark@rexx.org> * */ @@ -14,6 +14,7 @@ #define _WIN32_IE 0x0500 #define WINVER 0x500 #endif +#include <winsock2.h> #include <windows.h> #include <windowsx.h> #include <commctrl.h> @@ -207,6 +208,7 @@ #ifdef AEROGLASS HRESULT (WINAPI *_DwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset) = 0; HRESULT (WINAPI *_DwmIsCompositionEnabled)(BOOL *pfEnabled) = 0; +HRESULT (WINAPI *_DwmSetWindowAttribute)(HWND, DWORD, LPCVOID, DWORD) = 0; HTHEME (WINAPI *_OpenThemeData)(HWND hwnd, LPCWSTR pszClassList) = 0; HPAINTBUFFER (WINAPI *_BeginBufferedPaint)(HDC hdcTarget, const RECT *prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS *pPaintParams, HDC *phdc) = 0; HRESULT (WINAPI *_BufferedPaintSetAlpha)(HPAINTBUFFER hBufferedPaint, const RECT *prc, BYTE alpha) = 0; @@ -223,6 +225,7 @@ /* Needed for Rich Edit controls */ HANDLE hrichedit = 0; +HANDLE hmsftedit = 0; /* * MinGW Is missing a bunch of definitions @@ -263,6 +266,9 @@ #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif +#define _DW_DATA_TYPE_STRING 0 +#define _DW_DATA_TYPE_POINTER 1 + /* * For the dw*from_data() functions, a temporary file is required to write * the contents of the image to so it can be loaded by the Win32 API @@ -302,7 +308,7 @@ HFONT _DefaultFont = NULL; -#if (defined(BUILD_DLL) || defined(BUILD_HTML)) && !defined(__MINGW32__) +#if (defined(BUILD_DLL) || defined(BUILD_HTML)) LRESULT CALLBACK _browserWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); #endif LRESULT CALLBACK _colorwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2); @@ -336,6 +342,7 @@ HWND window; int id; void *signalfunction; + void *discfunction; void *data; } SignalHandler; @@ -665,9 +672,217 @@ } #endif +#ifdef AEROGLASS +/* Set _DW_DARK_MODE_ALLOWED to FALSE to disable dark mode. + * Set _DW_DARK_MODE_ALLOWED to TRUE for basic dark mode. + * Set _DW_DARK_MODE_ALLOWED to 2 for full dark mode. + */ +int _DW_DARK_MODE_ALLOWED = TRUE; +int _DW_DARK_MODE_SUPPORTED = FALSE; +int _DW_DARK_MODE_ENABLED = FALSE; + +typedef enum IMMERSIVE_HC_CACHE_MODE +{ + IHCM_USE_CACHED_VALUE, + IHCM_REFRESH +} IMMERSIVE_HC_CACHE_MODE; + +typedef enum _PreferredAppMode +{ + _Default, + _AllowDark, + _ForceDark, + _ForceLight, + _Max +} _PreferredAppMode; + +int CompareStringOrdinal(LPCWCH lpString1, int cchCount1, LPCWCH lpString2, int cchCount2, BOOL bIgnoreCase); +HTHEME (WINAPI * _OpenNcThemeData)(HWND, LPCWSTR) = NULL; +VOID (WINAPI * _RefreshImmersiveColorPolicyState)(VOID) = NULL; +BOOL (WINAPI * _GetIsImmersiveColorUsingHighContrast)(IMMERSIVE_HC_CACHE_MODE) = NULL; +BOOL (WINAPI * _ShouldAppsUseDarkMode)(VOID) = NULL; +BOOL (WINAPI * _AllowDarkModeForWindow)(HWND, BOOL) = NULL; +BOOL (WINAPI * _AllowDarkModeForApp)(BOOL) = NULL; +_PreferredAppMode (WINAPI * _SetPreferredAppMode)(_PreferredAppMode) = NULL; +BOOL (WINAPI * _IsDarkModeAllowedForWindow)(HWND) = NULL; +BOOL (WINAPI * _ShouldSystemUseDarkMode)(VOID) = NULL; + +BOOL IsHighContrast(VOID) +{ + HIGHCONTRASTW highContrast = { sizeof(highContrast) }; + if(SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(highContrast), &highContrast, FALSE)) + return highContrast.dwFlags & HCF_HIGHCONTRASTON; + return FALSE; +} + +void _dw_init_dark_mode(void) +{ + if(_DW_DARK_MODE_ALLOWED && dwVersion && huxtheme) + { + /* Dark mode is introduced in Windows 10 (1809) build 17763 */ + if(LOBYTE(LOWORD(dwVersion)) >= 10 && HIWORD(dwVersion) >= 17763) + { + _OpenNcThemeData = (HTHEME (WINAPI *)(HWND, LPCWSTR))GetProcAddress(huxtheme, MAKEINTRESOURCEA(49)); + _RefreshImmersiveColorPolicyState = (VOID (WINAPI *)(VOID))GetProcAddress(huxtheme, MAKEINTRESOURCEA(104)); + _GetIsImmersiveColorUsingHighContrast = (BOOL (WINAPI *)(IMMERSIVE_HC_CACHE_MODE))GetProcAddress(huxtheme, MAKEINTRESOURCEA(106)); + _ShouldAppsUseDarkMode = (BOOL (WINAPI *)(VOID))GetProcAddress(huxtheme, MAKEINTRESOURCEA(132)); + _AllowDarkModeForWindow = (BOOL (WINAPI *)(HWND, BOOL))GetProcAddress(huxtheme, MAKEINTRESOURCEA(133)); + if(HIWORD(dwVersion) < 18334) + _AllowDarkModeForApp = (BOOL (WINAPI *)(BOOL))GetProcAddress(huxtheme, MAKEINTRESOURCEA(135)); + else + _SetPreferredAppMode = (_PreferredAppMode (WINAPI *)(_PreferredAppMode))GetProcAddress(huxtheme, MAKEINTRESOURCEA(135)); + _IsDarkModeAllowedForWindow = (BOOL (WINAPI *)(HWND))GetProcAddress(huxtheme, MAKEINTRESOURCEA(137)); + _ShouldSystemUseDarkMode = (BOOL (WINAPI *)(VOID))GetProcAddress(huxtheme, MAKEINTRESOURCEA(138)); + } + /* Make sure we were able to load all the Dark Mode functions */ + if(_OpenNcThemeData && _RefreshImmersiveColorPolicyState && _ShouldAppsUseDarkMode && _AllowDarkModeForWindow && + (_AllowDarkModeForApp || _SetPreferredAppMode) && _IsDarkModeAllowedForWindow && _DwmSetWindowAttribute) + { + _DW_DARK_MODE_SUPPORTED = TRUE; + if(_AllowDarkModeForApp) + _AllowDarkModeForApp(TRUE); + else + _SetPreferredAppMode(_AllowDark); + _RefreshImmersiveColorPolicyState(); + _DW_DARK_MODE_ENABLED = _ShouldAppsUseDarkMode() && !IsHighContrast(); + } + } +} + +BOOL _CanThemeWindow(HWND window) +{ + TCHAR tmpbuf[100] = {0}; + LONG_PTR style = GetWindowLongPtr(window, GWL_STYLE); + + GetClassName(window, tmpbuf, 99); + + /* Some controls don't display properly with visual styles enabled */ + if(_tcsnicmp(tmpbuf, BUTTONCLASSNAME, _tcslen(BUTTONCLASSNAME)+1) == 0 && + (style & (BS_AUTOCHECKBOX | BS_CHECKBOX | BS_RADIOBUTTON))) + return FALSE; +#ifdef TOOLBAR + else if(_tcsnicmp(tmpbuf, TOOLBARCLASSNAME, _tcslen(TOOLBARCLASSNAME)+1) == 0) + { + /* If we aren't in full dark mode */ + if(_DW_DARK_MODE_ALLOWED != 2) + { + /* Enable or disable visual themes */ + if(_SetWindowTheme) + _SetWindowTheme(window, (style & TBSTYLE_FLAT) ? L"" : NULL, (style & TBSTYLE_FLAT) ? L"" : NULL); + } + return FALSE; + } +#endif + return TRUE; +} + +BOOL AllowDarkModeForWindow(HWND window, BOOL allow) +{ + if(_DW_DARK_MODE_SUPPORTED) + { + if(_CanThemeWindow(window)) + { + if(_DW_DARK_MODE_ALLOWED == 2) + { + if(_DW_DARK_MODE_ENABLED) + _SetWindowTheme(window, L"DarkMode_Explorer", NULL); + else + _SetWindowTheme(window, L"Explorer", NULL); + } + } + return _AllowDarkModeForWindow(window, allow); + } + return FALSE; +} + +BOOL IsColorSchemeChangeMessage(LPARAM lParam) +{ + BOOL is = FALSE; + if(lParam && CompareStringOrdinal((LPCWCH)lParam, -1, L"ImmersiveColorSet", -1, TRUE) == CSTR_EQUAL) + { + _RefreshImmersiveColorPolicyState(); + is = TRUE; + } + _GetIsImmersiveColorUsingHighContrast(IHCM_REFRESH); + return is; +} + +void RefreshTitleBarThemeColor(HWND window) +{ + BOOL dark = FALSE; + if (_IsDarkModeAllowedForWindow(window) && _ShouldAppsUseDarkMode() && !IsHighContrast()) + dark = TRUE; + _DwmSetWindowAttribute(window, 19, &dark, sizeof(dark)); +} + +/* Call this on a window to apply the style */ +BOOL CALLBACK _dw_set_child_window_theme(HWND window, LPARAM lParam) +{ + if(_DW_DARK_MODE_SUPPORTED) + { + AllowDarkModeForWindow(window, _DW_DARK_MODE_ENABLED); + SendMessageW(window, WM_THEMECHANGED, 0, 0); + } + return TRUE; +} +#endif + +/* Special wrappers for GetSysColor*() since they currently don't support + * dark mode, we will have to return modified colors when dark mode is enabled. + */ +DWORD _DW_GetSysColor(int nIndex) +{ + DWORD retval = GetSysColor(nIndex); +#ifdef AEROGLASS + if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) + { + const COLORREF darkBkColor = 0x383838; + const COLORREF darkTextColor = 0xFFFFFF; + + switch(nIndex) + { + case COLOR_3DFACE: + case COLOR_WINDOW: + retval = darkBkColor; + break; + case COLOR_WINDOWTEXT: + retval = darkTextColor; + break; + } + } +#endif + return retval; +} + +HBRUSH _DW_GetSysColorBrush(int nIndex) +{ + HBRUSH retval = GetSysColorBrush(nIndex); +#ifdef AEROGLASS + static HBRUSH darkBkColorBrush = 0; + + if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) + { + if(!darkBkColorBrush) + darkBkColorBrush = CreateSolidBrush(0x383838); + + switch(nIndex) + { + case COLOR_3DFACE: + case COLOR_WINDOW: + retval = darkBkColorBrush; + break; + case COLOR_WINDOWTEXT: + retval = _colors[DW_CLR_WHITE]; + break; + } + } +#endif + return retval; +} + /* This function adds a signal handler callback into the linked list. */ -void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data) +void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *discfunc, void *data) { SignalHandler *new = malloc(sizeof(SignalHandler)); @@ -675,6 +890,7 @@ new->window = window; new->id = id; new->signalfunction = signalfunction; + new->discfunction = discfunc; new->data = data; new->next = NULL; @@ -917,6 +1133,9 @@ */ if(_tcsnicmp(tmpbuf, EDITCLASSNAME, _tcslen(EDITCLASSNAME)+1)==0 || /* Entryfield */ _tcsnicmp(tmpbuf, BUTTONCLASSNAME, _tcslen(BUTTONCLASSNAME)+1)==0 || /* Button */ +#ifdef TOOLBAR + _tcsnicmp(tmpbuf, TOOLBARCLASSNAME, _tcslen(TOOLBARCLASSNAME)+1) == 0 || /* Toolbar */ +#endif _tcsnicmp(tmpbuf, COMBOBOXCLASSNAME, _tcslen(COMBOBOXCLASSNAME)+1)==0 || /* Combobox */ _tcsnicmp(tmpbuf, LISTBOXCLASSNAME, _tcslen(LISTBOXCLASSNAME)+1)==0 || /* List box */ _tcsnicmp(tmpbuf, UPDOWN_CLASS, _tcslen(UPDOWN_CLASS)+1)==0 || /* Spinbutton */ @@ -924,6 +1143,9 @@ _tcsnicmp(tmpbuf, WC_LISTVIEW, _tcslen(WC_LISTVIEW)+1)== 0 || /* Container */ _tcsnicmp(tmpbuf, WC_TREEVIEW, _tcslen(WC_TREEVIEW)+1)== 0) /* Tree */ return 1; + /* Special case for the notebook, can get focus and contains other items */ + if(_tcsnicmp(tmpbuf, WC_TABCONTROL, _tcslen(WC_TABCONTROL))==0) /* Notebook */ + return 2; return 0; } @@ -949,11 +1171,47 @@ return handle; } -int _focus_check_box(Box *box, HWND handle, int start, HWND defaultitem) +#define _DW_DIRECTION_FORWARD -1 +#define _DW_DIRECTION_BACKWARD 1 + +int _focus_check_box(Box *box, HWND handle, int start, int direction, HWND defaultitem); + +/* Internal comparision function */ +int _focus_comp(int direction, int z, int end) +{ + if(direction == _DW_DIRECTION_FORWARD) + return z > -1; + return z < end; +} + +int _focus_notebook(HWND hwnd, HWND handle, int start, int direction, HWND defaultitem) +{ + NotebookPage **array = (NotebookPage **)dw_window_get_data(hwnd, "_dw_array"); + int pageid = TabCtrl_GetCurSel(hwnd); + + if(pageid > -1 && array && array[pageid]) + { + Box *notebox; + + if(array[pageid]->hwnd) + { + notebox = (Box *)GetWindowLongPtr(array[pageid]->hwnd, GWLP_USERDATA); + + if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0, direction, defaultitem)) + return 1; + } + } + return 0; +} + +/* Handle box focus traversal in either direction */ +int _focus_check_box(Box *box, HWND handle, int start, int direction, HWND defaultitem) { int z; static HWND lasthwnd, firsthwnd; static int finish_searching; + int beg = (direction == _DW_DIRECTION_FORWARD) ? box->count-1 : 0; + int end = (direction == _DW_DIRECTION_FORWARD) ? -1 : box->count; /* Start is 2 when we have cycled completely and * need to set the focus to the last widget we found @@ -977,17 +1235,22 @@ firsthwnd = 0; } - for(z=box->count-1;z>-1;z--) + for(z=beg;_focus_comp(direction, z, end);z+=direction) { if(box->items[z].type == TYPEBOX) { Box *thisbox = (Box *)GetWindowLongPtr(box->items[z].hwnd, GWLP_USERDATA); - if(thisbox && _focus_check_box(thisbox, handle, start == 3 ? 3 : 0, defaultitem)) + if(thisbox && _focus_check_box(thisbox, handle, start == 3 ? 3 : 0, direction, defaultitem)) return 1; } else { + int type = _validate_focus(box->items[z].hwnd); + + /* Special case notebook, can focus and contains items */ + if(type == 2 && direction == _DW_DIRECTION_FORWARD && _focus_notebook(box->items[z].hwnd, handle, start, direction, defaultitem)) + return 1; if(box->items[z].hwnd == handle) { if(lasthwnd == handle && firsthwnd) @@ -1003,7 +1266,7 @@ if(!finish_searching) return 1; } - if(_validate_focus(box->items[z].hwnd)) + if(type > 0) { /* Start is 3 when we are looking for the * first valid item in the layout. @@ -1017,13 +1280,14 @@ } } + lasthwnd = _normalize_handle(box->items[z].hwnd); + if(!firsthwnd) - firsthwnd = _normalize_handle(box->items[z].hwnd); - - lasthwnd = _normalize_handle(box->items[z].hwnd); + firsthwnd = lasthwnd; } else { + /* Handle controls that contain other items */ TCHAR tmpbuf[100] = {0}; GetClassName(box->items[z].hwnd, tmpbuf, 99); @@ -1031,43 +1295,25 @@ if(_tcsncmp(tmpbuf, SplitbarClassName, _tcslen(SplitbarClassName)+1)==0) { /* Then try the bottom or right box */ - HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_bottomright"); - - if(mybox) - { - Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA); - - if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - - /* Try the top or left box */ - mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_topleft"); + HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, (direction == _DW_DIRECTION_FORWARD) ? "_dw_bottomright" : "_dw_topleft"); if(mybox) { Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA); - if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem)) + if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, direction, defaultitem)) return 1; } - } - else if(_tcsnicmp(tmpbuf, WC_TABCONTROL, _tcslen(WC_TABCONTROL))==0) /* Notebook */ - { - NotebookPage **array = (NotebookPage **)dw_window_get_data(box->items[z].hwnd, "_dw_array"); - int pageid = TabCtrl_GetCurSel(box->items[z].hwnd); - - if(pageid > -1 && array && array[pageid]) + + /* Try the top or left box */ + mybox = (HWND)dw_window_get_data(box->items[z].hwnd, (direction == _DW_DIRECTION_FORWARD) ? "_dw_topleft" : "_dw_bottomright"); + + if(mybox) { - Box *notebox; - - if(array[pageid]->hwnd) - { - notebox = (Box *)GetWindowLongPtr(array[pageid]->hwnd, GWLP_USERDATA); - - if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } + Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA); + + if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, direction, defaultitem)) + return 1; } } else if(_tcsnicmp(tmpbuf, ScrollClassName, _tcslen(ScrollClassName))==0) /* Scroll Box */ @@ -1075,146 +1321,14 @@ ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(box->items[z].hwnd, GWLP_USERDATA); Box *scrollbox = (Box *)GetWindowLongPtr(cinfo->combo, GWLP_USERDATA); - if(scrollbox && _focus_check_box(scrollbox, handle, start == 3 ? 3 : 0, defaultitem)) + if(scrollbox && _focus_check_box(scrollbox, handle, start == 3 ? 3 : 0, direction, defaultitem)) return 1; } } - } - } - return 0; -} - -int _focus_check_box_back(Box *box, HWND handle, int start, HWND defaultitem) -{ - int z; - static HWND lasthwnd, firsthwnd; - static int finish_searching; - - /* Start is 2 when we have cycled completely and - * need to set the focus to the last widget we found - * that was valid. - */ - if(start == 2) - { - if(lasthwnd) - SetFocus(lasthwnd); - return 0; - } - - /* Start is 1 when we are entering the function - * for the first time, it is zero when entering - * the function recursively. - */ - if(start == 1) - { - lasthwnd = handle; - finish_searching = 0; - firsthwnd = 0; - } - - for(z=0;z<box->count;z++) - { - if(box->items[z].type == TYPEBOX) - { - Box *thisbox = (Box *)GetWindowLongPtr(box->items[z].hwnd, GWLP_USERDATA); - - if(thisbox && _focus_check_box_back(thisbox, handle, start == 3 ? 3 : 0, defaultitem)) + /* Special case notebook, can focus and contains items */ + if(type == 2 && direction == _DW_DIRECTION_BACKWARD && _focus_notebook(box->items[z].hwnd, handle, start, direction, defaultitem)) return 1; } - else - { - if(box->items[z].hwnd == handle) - { - if(lasthwnd == handle && firsthwnd) - SetFocus(firsthwnd); - else if(lasthwnd == handle && !firsthwnd) - finish_searching = 1; - else - SetFocus(lasthwnd); - - /* If we aren't looking for the last handle, - * return immediately. - */ - if(!finish_searching) - return 1; - } - if(_validate_focus(box->items[z].hwnd)) - { - /* Start is 3 when we are looking for the - * first valid item in the layout. - */ - if(start == 3) - { - if(!defaultitem || (defaultitem && box->items[z].hwnd == defaultitem)) - { - SetFocus(_normalize_handle(box->items[z].hwnd)); - return 1; - } - } - - if(!firsthwnd) - firsthwnd = _normalize_handle(box->items[z].hwnd); - - lasthwnd = _normalize_handle(box->items[z].hwnd); - } - else - { - TCHAR tmpbuf[100] = {0}; - - GetClassName(box->items[z].hwnd, tmpbuf, 99); - - if(_tcsncmp(tmpbuf, SplitbarClassName, _tcslen(SplitbarClassName)+1)==0) - { - /* Try the top or left box */ - HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_topleft"); - - if(mybox) - { - Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA); - - if(splitbox && _focus_check_box_back(splitbox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - - /* Then try the bottom or right box */ - mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_bottomright"); - - if(mybox) - { - Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA); - - if(splitbox && _focus_check_box_back(splitbox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - } - else if(_tcsnicmp(tmpbuf, WC_TABCONTROL, _tcslen(WC_TABCONTROL))==0) /* Notebook */ - { - NotebookPage **array = (NotebookPage **)dw_window_get_data(box->items[z].hwnd, "_dw_array"); - int pageid = TabCtrl_GetCurSel(box->items[z].hwnd); - - if(pageid > -1 && array && array[pageid]) - { - Box *notebox; - - if(array[pageid]->hwnd) - { - notebox = (Box *)GetWindowLongPtr(array[pageid]->hwnd, GWLP_USERDATA); - - if(notebox && _focus_check_box_back(notebox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - } - } - else if(_tcsnicmp(tmpbuf, ScrollClassName, _tcslen(ScrollClassName))==0) /* Scroll Box */ - { - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(box->items[z].hwnd, GWLP_USERDATA); - Box *scrollbox = (Box *)GetWindowLongPtr(cinfo->combo, GWLP_USERDATA); - - if(scrollbox && _focus_check_box_back(scrollbox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - } - } } return 0; } @@ -1241,7 +1355,7 @@ if(thisbox) { - _focus_check_box(thisbox, handle, 3, thisbox->defaultitem); + _focus_check_box(thisbox, handle, 3, _DW_DIRECTION_FORWARD, thisbox->defaultitem); } } @@ -1249,6 +1363,9 @@ { HWND box, lastbox = GetParent(handle); + if(!lastbox) + lastbox = handle; + /* Find the toplevel window */ while((box = GetParent(lastbox))) { @@ -1272,7 +1389,7 @@ /* This function finds the current widget in the * layout and moves the current focus to the next item. */ -void _shift_focus(HWND handle) +void _shift_focus(HWND handle, int direction) { Box *thisbox; @@ -1287,33 +1404,11 @@ thisbox = (Box *)GetWindowLongPtr(lastbox, GWLP_USERDATA); if(thisbox) { - if(_focus_check_box(thisbox, handle, 1, 0) == 0) - _focus_check_box(thisbox, handle, 2, 0); - } -} - -/* This function finds the current widget in the - * layout and moves the current focus to the next item. - */ -void _shift_focus_back(HWND handle) -{ - Box *thisbox; - - HWND box, lastbox = GetParent(handle); - - /* Find the toplevel window */ - while((box = GetParent(lastbox))) - { - lastbox = box; - } - - thisbox = (Box *)GetWindowLongPtr(lastbox, GWLP_USERDATA); - if(thisbox) - { - if(_focus_check_box_back(thisbox, handle, 1, 0) == 0) - _focus_check_box_back(thisbox, handle, 2, 0); - } -} + if(_focus_check_box(thisbox, handle, 1, direction, 0) == 0) + _focus_check_box(thisbox, handle, 2, direction, 0); + } +} + /* This function calculates how much space the widgets and boxes require * and does expansion as necessary. */ @@ -1608,7 +1703,7 @@ { /* Then try the bottom or right box */ float *percent = (float *)dw_window_get_data(handle, "_dw_percent"); - int type = (int)dw_window_get_data(handle, "_dw_type"); + int type = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_type")); MoveWindow(handle, currentx + pad, currenty + pad, width, height, FALSE); @@ -1802,12 +1897,12 @@ char buffer[40]; int checkable; sprintf( buffer, "_dw_checkable%d", id ); - checkable = (int)dw_window_get_data(DW_HWND_OBJECT, buffer); + checkable = DW_POINTER_TO_INT(dw_window_get_data(DW_HWND_OBJECT, buffer)); if ( checkable ) { int is_checked; sprintf( buffer, "_dw_ischecked%d", id ); - is_checked = (int)dw_window_get_data(DW_HWND_OBJECT, buffer); + is_checked = DW_POINTER_TO_INT(dw_window_get_data(DW_HWND_OBJECT, buffer)); is_checked = (is_checked) ? DW_MIS_UNCHECKED : DW_MIS_CHECKED; dw_menu_item_set_state( window, id, is_checked ); } @@ -1818,7 +1913,7 @@ { int result = -1, taskbar = FALSE; SignalHandler *tmp = Root; - void (*windowfunc)(PVOID); + void (DWSIGNAL *windowfunc)(PVOID); ULONG origmsg = msg; /* Deal with translating some messages */ @@ -1849,7 +1944,7 @@ { if (!hWnd) { - int (*timerfunc)(void *) = tmp->signalfunction; + int (DWSIGNAL *timerfunc)(void *) = tmp->signalfunction; if (tmp->id == (int)mp1) { if (!timerfunc(tmp->data)) @@ -1864,7 +1959,7 @@ break; case WM_SETFOCUS: { - int (*setfocusfunc)(HWND, void *) = (int (*)(HWND, void *))tmp->signalfunction; + int (DWSIGNAL *setfocusfunc)(HWND, void *) = (int (*)(HWND, void *))tmp->signalfunction; if(hWnd == tmp->window) { @@ -1875,7 +1970,7 @@ break; case WM_SIZE: { - int (*sizefunc)(HWND, int, int, void *) = tmp->signalfunction; + int (DWSIGNAL *sizefunc)(HWND, int, int, void *) = tmp->signalfunction; if(hWnd == tmp->window) { result = sizefunc(tmp->window, LOWORD(mp2), HIWORD(mp2), tmp->data); @@ -1885,7 +1980,7 @@ break; case WM_LBUTTONDOWN: { - int (*buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; + int (DWSIGNAL *buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; if(hWnd == tmp->window) { @@ -1920,7 +2015,7 @@ break; case WM_LBUTTONUP: { - int (*buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; + int (DWSIGNAL *buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; if(hWnd == tmp->window) { @@ -1956,7 +2051,7 @@ case WM_MOUSEMOVE: { POINTS pts = MAKEPOINTS(mp2); - int (*motionfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; + int (DWSIGNAL *motionfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; if(hWnd == tmp->window) { @@ -1976,7 +2071,7 @@ break; case WM_CHAR: { - int (*keypressfunc)(HWND, char, int, int, void *, char *) = tmp->signalfunction; + int (DWSIGNAL *keypressfunc)(HWND, char, int, int, void *, char *) = tmp->signalfunction; if(hWnd == tmp->window || _toplevel_window(hWnd) == tmp->window) { @@ -1986,7 +2081,7 @@ WCHAR uc[2] = { 0 }; uc[0] = (WCHAR)mp1; - utf8 = WideToUTF8(uc); + utf8 = WideToUTF8(&uc[0]); #endif if(GetAsyncKeyState(VK_SHIFT) & 0x8000) @@ -2006,7 +2101,7 @@ break; case WM_CLOSE: { - int (*closefunc)(HWND, void *) = tmp->signalfunction; + int (DWSIGNAL *closefunc)(HWND, void *) = tmp->signalfunction; if(hWnd == tmp->window) { @@ -2019,7 +2114,7 @@ { PAINTSTRUCT ps; DWExpose exp; - int (*exposefunc)(HWND, DWExpose *, void *) = tmp->signalfunction; + int (DWSIGNAL *exposefunc)(HWND, DWExpose *, void *) = tmp->signalfunction; if ( hWnd == tmp->window ) { @@ -2051,18 +2146,18 @@ { if(tmp->window == tem->hdr.hwndFrom && !dw_window_get_data(tmp->window, "_dw_select_item")) { - int (*treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = tmp->signalfunction; + int (DWSIGNAL *treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = tmp->signalfunction; TVITEM tvi; - void **ptrs; - - tvi.mask = TVIF_HANDLE | TVIF_PARAM; + TCHAR textbuf[1025] = {0}, *textptr = textbuf; + + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT; tvi.hItem = tem->itemNew.hItem; + tvi.pszText = textbuf; + tvi.cchTextMax = 1024; TreeView_GetItem(tmp->window, &tvi); - ptrs = (void **)tvi.lParam; - if(ptrs) - result = treeselectfunc(tmp->window, tem->itemNew.hItem, (char *)ptrs[0], tmp->data, (void *)ptrs[1]); + result = treeselectfunc(tmp->window, tem->itemNew.hItem, WideToUTF8(textptr), tmp->data, (void *)tvi.lParam); tmp = NULL; } @@ -2071,7 +2166,7 @@ { if(tmp->window == tem->hdr.hwndFrom && tem->action == TVE_EXPAND) { - int (*treeexpandfunc)(HWND, HTREEITEM, void *) = tmp->signalfunction; + int (DWSIGNAL *treeexpandfunc)(HWND, HTREEITEM, void *) = tmp->signalfunction; result = treeexpandfunc(tmp->window, tem->itemNew.hItem, tmp->data); tmp = NULL; @@ -2081,12 +2176,13 @@ { if(tmp->window == tem->hdr.hwndFrom) { - int (*containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction; + int (DWSIGNAL *containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction; HTREEITEM hti; TVITEM tvi; TVHITTESTINFO thi; - void **ptrs = NULL; + void *itemdata = NULL; LONG x, y; + TCHAR textbuf[1025] = {0}, *textptr = textbuf; dw_pointer_query_pos(&x, &y); @@ -2099,15 +2195,17 @@ if(hti) { - tvi.mask = TVIF_HANDLE | TVIF_PARAM; + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT; tvi.hItem = hti; + tvi.pszText = textbuf; + tvi.cchTextMax = 1024; TreeView_GetItem(tmp->window, &tvi); TreeView_SelectItem(tmp->window, hti); - ptrs = (void **)tvi.lParam; + itemdata = (void *)tvi.lParam; } - containercontextfunc(tmp->window, ptrs ? (char *)ptrs[0] : NULL, x, y, tmp->data, ptrs ? ptrs[1] : NULL); + containercontextfunc(tmp->window, WideToUTF8(textptr), x, y, tmp->data, itemdata); tmp = NULL; } } @@ -2127,18 +2225,17 @@ if(iItem > -1) { - int (*treeselectfunc)(HWND, HWND, char *, void *, void *) = tmp->signalfunction; + int (DWSIGNAL *treeselectfunc)(HWND, HWND, char *, void *, void *) = tmp->signalfunction; + void **params; lvi.iItem = iItem; lvi.mask = LVIF_PARAM; ListView_GetItem(tmp->window, &lvi); - /* Seems to be having lParam as 1 which really sucks */ - if(lvi.lParam < 100) - lvi.lParam = 0; - - treeselectfunc(tmp->window, 0, (char *)lvi.lParam, tmp->data, 0); + params = (void **)lvi.lParam; + + treeselectfunc(tmp->window, 0, params ? (char *)params[_DW_DATA_TYPE_STRING] : NULL, tmp->data, params ? params[_DW_DATA_TYPE_POINTER] : NULL); tmp = NULL; } } @@ -2150,7 +2247,7 @@ NMHDR FAR *tem=(NMHDR FAR *)mp2; if(tmp->window == tem->hwndFrom && tem->code == tmp->message) { - int (*switchpagefunc)(HWND, unsigned long, void *) = tmp->signalfunction; + int (DWSIGNAL *switchpagefunc)(HWND, unsigned long, void *) = tmp->signalfunction; unsigned long num=dw_notebook_page_get(tem->hwndFrom); result = switchpagefunc(tem->hwndFrom, num, tmp->data); tmp = NULL; @@ -2161,7 +2258,7 @@ NMLISTVIEW FAR *tem=(NMLISTVIEW FAR *)mp2; if(tmp->window == tem->hdr.hwndFrom && tem->hdr.code == tmp->message) { - int (*columnclickfunc)(HWND, int, void *) = tmp->signalfunction; + int (DWSIGNAL *columnclickfunc)(HWND, int, void *) = tmp->signalfunction; result = columnclickfunc(tem->hdr.hwndFrom, tem->iSubItem, tmp->data); tmp = NULL; } @@ -2171,7 +2268,7 @@ NMUPDOWN FAR *tem=(NMUPDOWN FAR *)mp2; if(tmp->window == tem->hdr.hwndFrom && tem->hdr.code == UDN_DELTAPOS) { - int (*valuechangefunc)(HWND, int, void *) = tmp->signalfunction; + int (DWSIGNAL *valuechangefunc)(HWND, int, void *) = tmp->signalfunction; result = valuechangefunc(tmp->window, tem->iPos + tem->iDelta, tmp->data); tmp = NULL; } @@ -2180,16 +2277,16 @@ break; case WM_COMMAND: { - int (*clickfunc)(HWND, void *) = tmp->signalfunction; + int (DWSIGNAL *clickfunc)(HWND, void *) = tmp->signalfunction; HWND command; ULONG passthru = (ULONG)LOWORD(mp1); - ULONG message = HIWORD(mp1); - - command = (HWND)passthru; + ULONG message = (ULONG)HIWORD(mp1); + + command = (HWND)(uintptr_t)passthru; if (message == LBN_SELCHANGE || message == CBN_SELCHANGE) { - int (*listboxselectfunc)(HWND, int, void *) = tmp->signalfunction; + int (DWSIGNAL *listboxselectfunc)(HWND, int, void *) = tmp->signalfunction; if (tmp->message == LBN_SELCHANGE && tmp->window == (HWND)mp2) { @@ -2222,13 +2319,13 @@ /* * Call the user supplied callback */ - result = clickfunc((HWND)tmp->id, tmp->data); + result = clickfunc((HWND)(uintptr_t)tmp->id, tmp->data); tmp = NULL; } } /* this fires for checkable menu items */ else if ( tmp->window < (HWND)65536 && command == tmp->window && tmp->message != WM_TIMER ) { - _dw_toggle_checkable_menu_item( popup ? popup : tmp->window, (int)tmp->data ); + _dw_toggle_checkable_menu_item( popup ? popup : tmp->window, DW_POINTER_TO_INT(tmp->data) ); result = clickfunc(popup ? popup : tmp->window, tmp->data); tmp = NULL; } @@ -2239,7 +2336,7 @@ { TCHAR tmpbuf[100] = {0}; HWND handle = (HWND)mp2; - int (*valuechangefunc)(HWND, int, void *) = tmp->signalfunction; + int (DWSIGNAL *valuechangefunc)(HWND, int, void *) = tmp->signalfunction; if(!GetClassName(handle, tmpbuf, 99)) { @@ -2309,8 +2406,20 @@ } } break; + case WM_SETTINGCHANGE: + { + if(_DW_DARK_MODE_SUPPORTED && IsColorSchemeChangeMessage(mp2)) + { + _DW_DARK_MODE_ENABLED = _ShouldAppsUseDarkMode() && !IsHighContrast(); + + RefreshTitleBarThemeColor(hWnd); + _dw_set_child_window_theme(hWnd, 0); + EnumChildWindows(hWnd, _dw_set_child_window_theme, 0); + } + } + break; #endif -#ifdef AEROGLASS1 +#ifdef AEROGLASS1 case WM_ERASEBKGND: if(_dw_composition && (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & WS_EX_LAYERED)) { @@ -2325,7 +2434,7 @@ return TRUE; } break; -#endif +#endif case WM_PAINT: { PAINTSTRUCT ps; @@ -2390,6 +2499,28 @@ _resize_notebook_page(tem->hwndFrom, num); } + else if(tem->code == LVN_DELETEITEM) + { + NMLISTVIEW FAR *lem=(NMLISTVIEW FAR *)mp2; + LV_ITEM lvi; + void **params; + + memset(&lvi, 0, sizeof(LV_ITEM)); + + lvi.iItem = lem->iItem; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(lem->hdr.hwndFrom, &lvi); + params = (void **)lvi.lParam; + + /* Free row data */ + if(params) + { + if(params[_DW_DATA_TYPE_STRING]) + free(params[_DW_DATA_TYPE_STRING]); + free(params); + } + } } break; case WM_HSCROLL: @@ -2487,7 +2618,14 @@ case WM_MOUSEMOVE: _wndproc(hWnd, msg, mp1, mp2); break; -#ifdef AEROGLASS +#ifdef AEROGLASS + case WM_THEMECHANGED: + if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_SUPPORTED) + { + SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)_DW_GetSysColorBrush(COLOR_3DFACE)); + InvalidateRect(hWnd, NULL, TRUE); + } + break; case WM_ERASEBKGND: if(_dw_composition && (GetWindowLongPtr(_toplevel_window(hWnd), GWL_EXSTYLE) & WS_EX_LAYERED)) { @@ -2727,7 +2865,11 @@ /* These are the window classes which can * obtain input focus. */ - if (_tcsnicmp(tmpbuf, BUTTONCLASSNAME, _tcslen(BUTTONCLASSNAME)+1)==0) + if (_tcsnicmp(tmpbuf, BUTTONCLASSNAME, _tcslen(BUTTONCLASSNAME)+1)==0 +#ifdef TOOLBAR + || _tcsnicmp(tmpbuf, TOOLBARCLASSNAME, _tcslen(TOOLBARCLASSNAME)+1) == 0 +#endif + ) { /* Generate click on default item */ SignalHandler *tmp = Root; @@ -2740,7 +2882,7 @@ /* Make sure it's the right window, and the right ID */ if (tmp->window == handle) { - int (*clickfunc)(HWND, void *) = tmp->signalfunction; + int (DWSIGNAL *clickfunc)(HWND, void *) = tmp->signalfunction; clickfunc(tmp->window, tmp->data); tmp = NULL; } @@ -2835,20 +2977,20 @@ if (GetAsyncKeyState(VK_SHIFT) & 0x8000) { if (cinfo->combo) - _shift_focus_back(cinfo->combo); + _shift_focus(cinfo->combo, _DW_DIRECTION_BACKWARD); else if(cinfo->buddy) - _shift_focus_back(cinfo->buddy); + _shift_focus(cinfo->buddy, _DW_DIRECTION_BACKWARD); else - _shift_focus_back(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_BACKWARD); } else { if (cinfo->combo) - _shift_focus(cinfo->combo); + _shift_focus(cinfo->combo, _DW_DIRECTION_FORWARD); else if(cinfo->buddy) - _shift_focus(cinfo->buddy); + _shift_focus(cinfo->buddy, _DW_DIRECTION_FORWARD); else - _shift_focus(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_FORWARD); } return FALSE; } @@ -2858,6 +3000,7 @@ if ( cinfo->clickdefault ) { _click_default(cinfo->clickdefault); + return (LRESULT)TRUE; } else { @@ -2870,6 +3013,7 @@ if ( mycinfo && mycinfo->clickdefault ) { _click_default( mycinfo->clickdefault ); + return (LRESULT)TRUE; } } } @@ -2904,6 +3048,18 @@ case WM_CTLCOLORDLG: { ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr((HWND)mp2, GWLP_USERDATA); + + if(msg == WM_CTLCOLORBTN) + { + /* Groupbox color info is on the frame window it is attached to */ + if(GetWindowLongPtr((HWND)mp2, GWL_STYLE) & BS_GROUPBOX) + { + Box *framebox = (Box *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + if(framebox) + thiscinfo = &framebox->cinfo; + } + } + if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) { int thisback = thiscinfo->back; @@ -2912,11 +3068,15 @@ if(thiscinfo->fore != DW_CLR_DEFAULT) { int fore = _internal_color(thiscinfo->fore); - + SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(fore), DW_GREEN_VALUE(fore), DW_BLUE_VALUE(fore))); } +#ifdef AEROGLASS + else if(thiscinfo->fore == DW_CLR_DEFAULT && _DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) + SetTextColor((HDC)mp1, _DW_GetSysColor(COLOR_WINDOWTEXT)); +#endif /* Handle background */ if(thiscinfo->back == DW_RGB_TRANSPARENT) { @@ -2927,12 +3087,12 @@ } if(thisback == DW_CLR_DEFAULT) { - HBRUSH hbr = GetSysColorBrush(COLOR_3DFACE); - - SetBkColor((HDC)mp1, GetSysColor(COLOR_3DFACE)); + HBRUSH hbr = _DW_GetSysColorBrush(COLOR_3DFACE); + + SetBkColor((HDC)mp1, _DW_GetSysColor(COLOR_3DFACE)); SelectObject((HDC)mp1, hbr); - return (LONG)hbr; + return (LRESULT)(intptr_t)hbr; } else if(thisback != -1 && thisback != DW_RGB_TRANSPARENT) { @@ -2947,10 +3107,11 @@ DW_GREEN_VALUE(back), DW_BLUE_VALUE(back))); SelectObject((HDC)mp1, thiscinfo->hbrush); - return (LONG)thiscinfo->hbrush; + return (LRESULT)(intptr_t)thiscinfo->hbrush; } } #ifdef AEROGLASS + /* First handle the transparent or layered cases */ switch(msg) { case WM_CTLCOLORSTATIC: @@ -2968,11 +3129,44 @@ DeleteObject(thiscinfo->hbrush); thiscinfo->hbrush = CreateSolidBrush(_dw_transparencykey); SelectObject((HDC)mp1, thiscinfo->hbrush); - return (LONG)thiscinfo->hbrush; + return (LRESULT)thiscinfo->hbrush; } } } } + /* Second we handle the dark mode cases */ + switch(msg) + { + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORBTN: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORMSGBOX: + case WM_CTLCOLORSCROLLBAR: + case WM_CTLCOLORDLG: + { + if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) + { + ColorInfo *parentcinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + int thisback = thiscinfo ? thiscinfo->back : -1; + + if(thisback == DW_RGB_TRANSPARENT && parentcinfo) + thisback = parentcinfo->back; + + if(!thiscinfo || (thiscinfo && (thiscinfo->fore == DW_CLR_DEFAULT || thiscinfo->fore == -1))) + SetTextColor((HDC)mp1, _DW_GetSysColor(COLOR_WINDOWTEXT)); + if(!thiscinfo || (thiscinfo && (thisback == DW_CLR_DEFAULT || thisback == -1 || thisback == DW_RGB_TRANSPARENT))) + { + HBRUSH hbr = _DW_GetSysColorBrush(COLOR_3DFACE); + + SetBkColor((HDC)mp1, _DW_GetSysColor(COLOR_3DFACE)); + + SelectObject((HDC)mp1, hbr); + return (LRESULT)(intptr_t)hbr; + } + } + } + } #endif } break; @@ -3000,12 +3194,47 @@ case WM_MOUSEMOVE: _wndproc(hWnd, msg, mp1, mp2); break; +#ifdef AEROGLASS + case WM_THEMECHANGED: + if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_SUPPORTED) + { + if(!continfo || continfo->cinfo.back == -1 || continfo->cinfo.back == DW_CLR_DEFAULT) + { + COLORREF bk = _DW_GetSysColor(COLOR_WINDOW); + + ListView_SetBkColor(hWnd, bk); + ListView_SetTextBkColor(hWnd, bk); + } + if(!continfo || continfo->cinfo.fore == -1 || continfo->cinfo.fore == DW_CLR_DEFAULT) + ListView_SetTextColor(hWnd, _DW_GetSysColor(COLOR_WINDOWTEXT)); + } + break; +#endif case WM_PAINT: if(continfo->cinfo.pOldProc && (continfo->even != DW_RGB_TRANSPARENT || continfo->odd != DW_RGB_TRANSPARENT)) { RECT rectUpd, rectDestin, rectThis, *rect = &rectThis; int iItems, iTop, i; - COLORREF c; + COLORREF c, odd, even; + unsigned long temp = _internal_color(continfo->odd); + + /* Create the colors based on the current theme */ + if(continfo->odd == DW_CLR_DEFAULT) + { +#ifdef AEROGLASS + if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) + odd = RGB(100,100,100); + else +#endif + odd = RGB(230, 230, 230); + } + else + odd = RGB(DW_RED_VALUE(temp), DW_GREEN_VALUE(temp), DW_BLUE_VALUE(temp)); + temp = _internal_color(continfo->even); + if(continfo->even == DW_CLR_DEFAULT) + even = DW_RGB_TRANSPARENT; + else + even = RGB(DW_RED_VALUE(temp), DW_GREEN_VALUE(temp), DW_BLUE_VALUE(temp)); /* Load the default background color for the first pass */ ListView_SetTextBkColor(hWnd, continfo->cinfo.back != -1 ? continfo->cinfo.back : ListView_GetBkColor(hWnd)); @@ -3024,7 +3253,7 @@ if(ListView_GetItemRect(hWnd, i, rect, LVIR_BOUNDS) && IntersectRect(&rectDestin, &rectUpd, rect)) { /* change text background colour accordingly */ - c = (i % 2) ? continfo->odd : continfo->even; + c = (i % 2) ? odd : even; if(c != DW_RGB_TRANSPARENT) { @@ -3043,13 +3272,14 @@ { LV_ITEM lvi; int iItem; + void **params = NULL; if(LOWORD(mp1) == '\t') { if(GetAsyncKeyState(VK_SHIFT) & 0x8000) - _shift_focus_back(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_BACKWARD); else - _shift_focus(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_FORWARD); return FALSE; } @@ -3066,6 +3296,7 @@ lvi.mask = LVIF_PARAM; ListView_GetItem(hWnd, &lvi); + params = (void **)lvi.lParam; } { @@ -3075,13 +3306,9 @@ { if(tmp->message == NM_DBLCLK && tmp->window == hWnd) { - int (*containerselectfunc)(HWND, char *, void *) = tmp->signalfunction; - - /* Seems to be having lParam as 1 which really sucks */ - if(lvi.lParam < 100) - lvi.lParam = 0; - - containerselectfunc(tmp->window, (char *)lvi.lParam, tmp->data); + int (DWSIGNAL *containerselectfunc)(HWND, char *, void *, void *) = tmp->signalfunction; + + containerselectfunc(tmp->window, params ? params[_DW_DATA_TYPE_STRING] : NULL, tmp->data, params ? params[_DW_DATA_TYPE_POINTER] : NULL); tmp = NULL; } if(tmp) @@ -3093,16 +3320,17 @@ case WM_CONTEXTMENU: { SignalHandler *tmp = Root; - + void **params = NULL; while(tmp) { if(tmp->message == NM_RCLICK && tmp->window == hWnd) { - int (*containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction; + int (DWSIGNAL *containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction; LONG x,y; LV_ITEM lvi; int iItem; LVHITTESTINFO lhi; + TCHAR textbuf[1025] = {0}; dw_pointer_query_pos(&x, &y); @@ -3118,17 +3346,16 @@ if(iItem > -1) { lvi.iItem = iItem; - lvi.mask = LVIF_PARAM; + lvi.pszText = textbuf; + lvi.cchTextMax = 1024; + lvi.mask = LVIF_PARAM | LVIF_TEXT; ListView_GetItem(tmp->window, &lvi); ListView_SetSelectionMark(tmp->window, iItem); + params = (void **)lvi.lParam; } - /* Seems to be having lParam as 1 which really sucks */ - if(lvi.lParam < 100) - lvi.lParam = 0; - - containercontextfunc(tmp->window, (char *)lvi.lParam, x, y, tmp->data, NULL); + containercontextfunc(tmp->window, params ? params[_DW_DATA_TYPE_STRING] : NULL, x, y, tmp->data, (void *)lvi.lParam); tmp = NULL; } if(tmp) @@ -3143,7 +3370,7 @@ return CallWindowProc(continfo->cinfo.pOldProc, hWnd, msg, mp1, mp2); } -LRESULT CALLBACK _treewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) +LRESULT CALLBACK _simplewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) { ContainerInfo *cinfo; LRESULT ret = -1; @@ -3160,9 +3387,9 @@ if(ret != TRUE && LOWORD(mp1) == '\t') { if(GetAsyncKeyState(VK_SHIFT) & 0x8000) - _shift_focus_back(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_BACKWARD); else - _shift_focus(hWnd); + _shift_focus(hWnd, _DW_DIRECTION_FORWARD); return FALSE; } break; @@ -3177,6 +3404,25 @@ return ret; } +LRESULT CALLBACK _treewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ +#ifdef AEROGLASS + if(msg == WM_THEMECHANGED) + { + if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_SUPPORTED) + { + ContainerInfo *continfo = (ContainerInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + if(!continfo || continfo->cinfo.back == -1 || continfo->cinfo.back == DW_CLR_DEFAULT) + TreeView_SetBkColor(hWnd, _DW_GetSysColor(COLOR_WINDOW)); + if(!continfo || continfo->cinfo.fore == -1 || continfo->cinfo.fore == DW_CLR_DEFAULT) + TreeView_SetTextColor(hWnd, _DW_GetSysColor(COLOR_WINDOWTEXT)); + } + } +#endif + return _simplewndproc(hWnd, msg, mp1, mp2); +} + void _changebox(Box *thisbox, int percent, int type) { int z; @@ -3230,7 +3476,7 @@ MoveWindow(handle2, x - newx, 0, newx, y, FALSE); _do_resize(tmp, newx - 1, y - 1); - dw_window_set_data(hwnd, "_dw_start", (void *)newx); + dw_window_set_data(hwnd, "_dw_start", DW_INT_TO_POINTER(newx)); } else { @@ -3250,7 +3496,7 @@ MoveWindow(handle1, 0, 0, x, newy, FALSE); _do_resize(tmp, x - 1, newy - 1); - dw_window_set_data(hwnd, "_dw_start", (void *)newy); + dw_window_set_data(hwnd, "_dw_start", DW_INT_TO_POINTER(newy)); } ShowWindow(handle1, SW_SHOW); @@ -3333,21 +3579,26 @@ case WM_ACTIVATE: case WM_SETFOCUS: return FALSE; - +#ifdef AEROGLASS + case WM_THEMECHANGED: + if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_SUPPORTED) + InvalidateRect(hwnd, NULL, TRUE); + break; +#endif case WM_PAINT: { PAINTSTRUCT ps; HDC hdcPaint; - int type = (int)dw_window_get_data(hwnd, "_dw_type"); - int start = (int)dw_window_get_data(hwnd, "_dw_start"); + int type = DW_POINTER_TO_INT(dw_window_get_data(hwnd, "_dw_type")); + int start = DW_POINTER_TO_INT(dw_window_get_data(hwnd, "_dw_start")); BeginPaint(hwnd, &ps); if((hdcPaint = GetDC(hwnd)) != NULL) { unsigned long cx, cy; - HBRUSH oldBrush = SelectObject(hdcPaint, GetSysColorBrush(COLOR_3DFACE)); - HPEN oldPen = SelectObject(hdcPaint, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DFACE))); + HBRUSH oldBrush = SelectObject(hdcPaint, _DW_GetSysColorBrush(COLOR_3DFACE)); + HPEN oldPen = SelectObject(hdcPaint, CreatePen(PS_SOLID, 1, _DW_GetSysColor(COLOR_3DFACE))); dw_window_get_pos_size(hwnd, NULL, NULL, &cx, &cy); @@ -3377,7 +3628,7 @@ case WM_MOUSEMOVE: { float *percent = (float *)dw_window_get_data(hwnd, "_dw_percent"); - int type = (int)dw_window_get_data(hwnd, "_dw_type"); + int type = DW_POINTER_TO_INT(dw_window_get_data(hwnd, "_dw_type")); int start; if(type == DW_HORZ) @@ -3440,6 +3691,12 @@ InvalidateRgn(hwnd, NULL, TRUE); return ret; } +#ifdef AEROGLASS + case WM_THEMECHANGED: + if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_SUPPORTED) + InvalidateRect(hwnd, NULL, TRUE); + break; +#endif case WM_PAINT: { HDC hdcPaint; @@ -3457,10 +3714,40 @@ hdcPaint = BeginPaint(hwnd, &ps); if(hfont) oldfont = (HFONT)SelectObject(hdcPaint, hfont); - rc.top = rc.left = 0; - rc.right = cx; - rc.bottom = cy; - DrawStatusText(hdcPaint, &rc, tempbuf, 0); + + SetRect(&rc, 0, 0, cx, cy); + + /* If we are in full dark mode, or we have custom colors selected... + * we will draw the status window ourselves... otherwise DrawStatusText() + */ + if( +#ifdef AEROGLASS + (_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) || +#endif + (cinfo && cinfo->fore != -1 && cinfo->fore != DW_CLR_DEFAULT && + cinfo->back !=- -1 && cinfo->back != DW_CLR_DEFAULT)) + { + ULONG fore = (cinfo && (cinfo->fore != -1 && cinfo->fore != DW_CLR_DEFAULT)) ? _internal_color(cinfo->fore) : DW_RGB_TRANSPARENT; + ULONG back = (cinfo && (cinfo->back != -1 && cinfo->back != DW_CLR_DEFAULT)) ? _internal_color(cinfo->back) : DW_RGB_TRANSPARENT; + HBRUSH hbrback, hbrfore; + hbrfore = fore != DW_RGB_TRANSPARENT ? CreateSolidBrush(RGB(DW_RED_VALUE(fore), DW_GREEN_VALUE(fore), DW_BLUE_VALUE(fore))) : NULL; + hbrback = back != DW_RGB_TRANSPARENT ? CreateSolidBrush(RGB(DW_RED_VALUE(back), DW_GREEN_VALUE(back), DW_BLUE_VALUE(back))) : NULL; + /* Fill with the background color */ + FillRect(hdcPaint, &rc, hbrback ? hbrback : _DW_GetSysColorBrush(COLOR_3DFACE)); + /* Dwaw a border around it */ + FrameRect(hdcPaint, &rc, hbrfore ? hbrfore : _DW_GetSysColorBrush(COLOR_WINDOWTEXT)); + SetRect(&rc, 3, 1, cx -1, cy - 1); + SetTextColor(hdcPaint, fore != DW_RGB_TRANSPARENT ? RGB(DW_RED_VALUE(fore), DW_GREEN_VALUE(fore), DW_BLUE_VALUE(fore)) : _DW_GetSysColor(COLOR_WINDOWTEXT)); + SetBkMode(hdcPaint, TRANSPARENT); + /* Draw the text in the middle */ + ExtTextOut(hdcPaint, 3, 1, ETO_CLIPPED, &rc, tempbuf, (UINT)_tcslen(tempbuf), NULL); + if(hbrfore) + DeleteObject(hbrfore); + if(hbrback) + DeleteObject(hbrback); + } + else + DrawStatusText(hdcPaint, &rc, tempbuf, 0); if(hfont && oldfont) SelectObject(hdcPaint, oldfont); if(hfont) @@ -3656,7 +3943,7 @@ { if(tmp->message == WM_COMMAND) { - int (*clickfunc)(HWND, void *) = tmp->signalfunction; + int (DWSIGNAL *clickfunc)(HWND, void *) = tmp->signalfunction; /* Make sure it's the right window, and the right ID */ if(tmp->window == hwnd) @@ -3692,7 +3979,7 @@ { if(tmp->message == WM_COMMAND) { - int (*clickfunc)(HWND, void *) = tmp->signalfunction; + int (DWSIGNAL *clickfunc)(HWND, void *) = tmp->signalfunction; /* Make sure it's the right window, and the right ID */ if(tmp->window == hwnd) @@ -3708,18 +3995,18 @@ if(LOWORD(mp1) == '\t') { if(GetAsyncKeyState(VK_SHIFT) & 0x8000) - _shift_focus_back(hwnd); + _shift_focus(hwnd, _DW_DIRECTION_BACKWARD); else - _shift_focus(hwnd); + _shift_focus(hwnd, _DW_DIRECTION_FORWARD); return FALSE; } } break; case WM_KEYDOWN: if(mp1 == VK_LEFT || mp1 == VK_UP) - _shift_focus_back(hwnd); + _shift_focus(hwnd, _DW_DIRECTION_BACKWARD); if(mp1 == VK_RIGHT || mp1 == VK_DOWN) - _shift_focus(hwnd); + _shift_focus(hwnd, _DW_DIRECTION_FORWARD); break; } @@ -3850,27 +4137,6 @@ } #endif -/* Initialize thread local values to the defaults */ -void _init_thread(void) -{ - COLORREF foreground = RGB(128,128,128); - COLORREF background = DW_RGB_TRANSPARENT; -#ifdef GDIPLUS - ARGB gpfore = MAKEARGB(255, 128, 128, 128); - GpBrush *brush; - GpPen *pen; - - GdipCreatePen1(gpfore, 1.0, UnitPixel, &pen); - TlsSetValue(_gpPen, (LPVOID)pen); - GdipCreateSolidFill(gpfore, &brush); - TlsSetValue(_gpBrush, (LPVOID)brush); -#endif - TlsSetValue(_foreground, (LPVOID)foreground); - TlsSetValue(_background, (LPVOID)background); - TlsSetValue(_hPen, CreatePen(PS_SOLID, 1, foreground)); - TlsSetValue(_hBrush, CreateSolidBrush(foreground)); -} - /* * Initializes the Dynamic Windows engine. * Parameters: @@ -3920,6 +4186,37 @@ memset(lookup, 0, sizeof(HICON) * ICON_INDEX_LIMIT); + /* We need the version to check capability like up-down controls */ + dwVersion = GetVersion(); + dwComctlVer = GetDllVersion(TEXT("comctl32.dll")); + + /* We need to initialize dark mode, and thus the aero/theme subsystems before registering our window classes */ + if((huxtheme = LoadLibrary(TEXT("uxtheme")))) + _SetWindowTheme = (HRESULT (WINAPI *)(HWND, LPCWSTR, LPCWSTR ))GetProcAddress(huxtheme, "SetWindowTheme"); +#ifdef AEROGLASS + /* Attempt to load the Desktop Window Manager and Theme library */ + if(huxtheme && (hdwm = LoadLibrary(TEXT("dwmapi")))) + { + _DwmExtendFrameIntoClientArea = (HRESULT (WINAPI *)(HWND, const MARGINS *))GetProcAddress(hdwm, "DwmExtendFrameIntoClientArea"); + _DwmSetWindowAttribute = (HRESULT (WINAPI *)(HWND, DWORD, LPCVOID, DWORD))GetProcAddress(hdwm, "DwmSetWindowAttribute"); + if((_DwmIsCompositionEnabled = (HRESULT (WINAPI *)(BOOL *))GetProcAddress(hdwm, "DwmIsCompositionEnabled"))) + _DwmIsCompositionEnabled(&_dw_composition); + _OpenThemeData = (HTHEME (WINAPI *)(HWND, LPCWSTR))GetProcAddress(huxtheme, "OpenThemeData"); + _BeginBufferedPaint = (HPAINTBUFFER (WINAPI *)(HDC, const RECT *, BP_BUFFERFORMAT, BP_PAINTPARAMS *, HDC *))GetProcAddress(huxtheme, "BeginBufferedPaint"); + _BufferedPaintSetAlpha = (HRESULT (WINAPI *)(HPAINTBUFFER, const RECT *, BYTE))GetProcAddress(huxtheme, "BufferedPaintSetAlpha"); + _DrawThemeTextEx = (HRESULT (WINAPI *)(HTHEME, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const DTTOPTS *))GetProcAddress(huxtheme, "DrawThemeTextEx"); + _EndBufferedPaint = (HRESULT (WINAPI *)(HPAINTBUFFER, BOOL))GetProcAddress(huxtheme, "EndBufferedPaint"); + _CloseThemeData = (HRESULT (WINAPI *)(HTHEME))GetProcAddress(huxtheme, "CloseThemeData"); + _dw_init_dark_mode(); + } + /* In case of error close the library if needed */ + else if(hdwm) + { + FreeLibrary(hdwm); + hdwm = 0; + } +#endif + /* Register the generic Dynamic Windows class */ memset(&wc, 0, sizeof(WNDCLASS)); wc.style = CS_DBLCLKS; @@ -3962,7 +4259,7 @@ wc.lpfnWndProc = (WNDPROC)_framewndproc; wc.cbClsExtra = 0; wc.cbWndExtra = 32; - wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = (HBRUSH)_DW_GetSysColorBrush(COLOR_3DFACE); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszMenuName = NULL; wc.lpszClassName = FRAMECLASSNAME; @@ -3975,14 +4272,14 @@ wc.lpfnWndProc = (WNDPROC)_statuswndproc; wc.cbClsExtra = 0; wc.cbWndExtra = 32; - wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_3DFACE); + wc.hbrBackground = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszMenuName = NULL; wc.lpszClassName = StatusbarClassName; RegisterClass(&wc); -#if (defined(BUILD_DLL) || defined(BUILD_HTML)) && !defined(__MINGW32__) +#if (defined(BUILD_DLL) || defined(BUILD_HTML)) /* Register HTML renderer class */ memset(&wc, 0, sizeof(WNDCLASS)); wc.lpfnWndProc = (WNDPROC)_browserWindowProc; @@ -4036,10 +4333,6 @@ /* Create empty box data */ SetWindowLongPtr(DW_HWND_OBJECT, GWLP_USERDATA, (LONG_PTR)calloc(sizeof(Box), 1)); - /* We need the version to check capability like up-down controls */ - dwVersion = GetVersion(); - dwComctlVer = GetDllVersion(TEXT("comctl32.dll")); - /* Initialize Security for named events and memory */ InitializeSecurityDescriptor(&_dwsd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&_dwsd, TRUE, (PACL) NULL, FALSE); @@ -4067,36 +4360,16 @@ GdiplusStartup(&gdiplusToken, &si, NULL); #endif - /* GDI+ Needs to be initialized before calling _init_thread(); */ - _init_thread(); - - if((huxtheme = LoadLibrary(TEXT("uxtheme")))) - _SetWindowTheme = (HRESULT (WINAPI *)(HWND, LPCWSTR, LPCWSTR ))GetProcAddress(huxtheme, "SetWindowTheme"); -#ifdef AEROGLASS - /* Attempt to load the Desktop Window Manager and Theme library */ - if(huxtheme && (hdwm = LoadLibrary(TEXT("dwmapi")))) - { - _DwmExtendFrameIntoClientArea = (HRESULT (WINAPI *)(HWND, const MARGINS *))GetProcAddress(hdwm, "DwmExtendFrameIntoClientArea"); - if((_DwmIsCompositionEnabled = (HRESULT (WINAPI *)(BOOL *))GetProcAddress(hdwm, "DwmIsCompositionEnabled"))) - _DwmIsCompositionEnabled(&_dw_composition); - _OpenThemeData = (HTHEME (WINAPI *)(HWND, LPCWSTR))GetProcAddress(huxtheme, "OpenThemeData"); - _BeginBufferedPaint = (HPAINTBUFFER (WINAPI *)(HDC, const RECT *, BP_BUFFERFORMAT, BP_PAINTPARAMS *, HDC *))GetProcAddress(huxtheme, "BeginBufferedPaint"); - _BufferedPaintSetAlpha = (HRESULT (WINAPI *)(HPAINTBUFFER, const RECT *, BYTE))GetProcAddress(huxtheme, "BufferedPaintSetAlpha"); - _DrawThemeTextEx = (HRESULT (WINAPI *)(HTHEME, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const DTTOPTS *))GetProcAddress(huxtheme, "DrawThemeTextEx"); - _EndBufferedPaint = (HRESULT (WINAPI *)(HPAINTBUFFER, BOOL))GetProcAddress(huxtheme, "EndBufferedPaint"); - _CloseThemeData = (HRESULT (WINAPI *)(HTHEME))GetProcAddress(huxtheme, "CloseThemeData"); - } - /* In case of error close the library if needed */ - else if(hdwm) - { - FreeLibrary(hdwm); - hdwm = 0; - } -#endif + /* GDI+ Needs to be initialized before calling _dw_init_thread(); */ + _dw_init_thread(); + #ifdef RICHEDIT - /* Attempt to load rich edit library */ - if(!(hrichedit = LoadLibrary("riched20"))) - hrichedit = LoadLibrary("riched32"); + /* Attempt to load rich edit library: 4.1, 3/2.0 and 1.0 */ + if(!(hmsftedit = LoadLibrary(TEXT("msftedit")))) + { + if(!(hrichedit = LoadLibrary(TEXT("riched20")))) + hrichedit = LoadLibrary(TEXT("riched32")); + } #endif return 0; } @@ -4242,6 +4515,9 @@ MSG msg; void *tmp; + if(!dialog) + return NULL; + while (GetMessage(&msg,NULL,0,0)) { if(msg.hwnd == NULL && msg.message == WM_TIMER) @@ -4347,6 +4623,17 @@ int rc; RECT rect; +#ifdef AEROGLASS + if(_DW_DARK_MODE_SUPPORTED) + { + /* Try to enable dark mode support if our OS supports it */ + _dw_set_child_window_theme(handle, 0); + EnumChildWindows(handle, _dw_set_child_window_theme, 0); + if(GetParent(handle) == HWND_DESKTOP) + RefreshTitleBarThemeColor(handle); + } +#endif + GetClientRect(handle, &rect); /* If the client area is 0x0 then call the autosize routine */ @@ -4383,7 +4670,7 @@ if(handle < (HWND)65536) { char buffer[31] = {0}; - ULONG id = (ULONG)handle; + ULONG id = (ULONG)(uintptr_t)handle; _snprintf(buffer, 30, "_dw_id%ld", id); menu = (HMENU)dw_window_get_data(DW_HWND_OBJECT, buffer); @@ -4726,7 +5013,8 @@ } /* Entryfields and MLE */ else if(_tcsnicmp(tmpbuf, EDITCLASSNAME, _tcslen(EDITCLASSNAME)+1) == 0 || - _tcsnicmp(tmpbuf, RICHEDIT_CLASS, _tcslen(RICHEDIT_CLASS)+1) == 0) + _tcsnicmp(tmpbuf, RICHEDIT_CLASS, _tcslen(RICHEDIT_CLASS)+1) == 0 || + _tcsnicmp(tmpbuf, MSFTEDIT_CLASS, _tcslen(MSFTEDIT_CLASS)+1) == 0) { LONG style = GetWindowLong(handle, GWL_STYLE); if((style & ES_MULTILINE)) @@ -5008,7 +5296,7 @@ italic = " Italic"; height = MulDiv(abs(lf.lfHeight), 72, GetDeviceCaps (hdc, LOGPIXELSY)); ReleaseDC(handle, hdc); - _snprintf( str, 100, "%d.%s%s%s", height, lf.lfFaceName, bold, italic ); + _snprintf( str, 100, "%d.%s%s%s", height, WideToUTF8(lf.lfFaceName), bold, italic ); } } if ( oldfont ) @@ -5117,13 +5405,13 @@ */ void API dw_window_set_pointer(HWND handle, int pointertype) { - HCURSOR cursor = pointertype < 65536 ? LoadCursor(NULL, MAKEINTRESOURCE(pointertype)) : (HCURSOR)pointertype; + HCURSOR cursor = pointertype < 65536 ? LoadCursor(NULL, MAKEINTRESOURCE(pointertype)) : (HCURSOR)(intptr_t)pointertype; if(!pointertype) dw_window_set_data(handle, "_dw_cursor", 0); else { - dw_window_set_data(handle, "_dw_cursor", (void *)cursor); + dw_window_set_data(handle, "_dw_cursor", DW_POINTER(cursor)); SetCursor(cursor); } } @@ -5337,7 +5625,12 @@ DWInstance, NULL); + /* Disable visual styles by default */ + if(_SetWindowTheme) + _SetWindowTheme(newbox->grouphwnd, L"", L""); + SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox); + newbox->cinfo.pOldProc = SubclassWindow(hwndframe, _colorwndproc); dw_window_set_font(hwndframe, DefaultFont); return hwndframe; } @@ -5360,7 +5653,7 @@ WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, &ccs); return hwndframe; @@ -5373,13 +5666,13 @@ */ HWND API dw_html_new(unsigned long id) { -#if (defined(BUILD_DLL) || defined(BUILD_HTML)) && !defined(__MINGW32__) +#if (defined(BUILD_DLL) || defined(BUILD_HTML)) return CreateWindow(BrowserClassName, NULL, WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); #else @@ -5388,7 +5681,7 @@ #endif } -#if (defined(BUILD_DLL) || defined(BUILD_HTML)) && !defined(__MINGW32__) +#if (defined(BUILD_DLL) || defined(BUILD_HTML)) void _dw_html_action(HWND hwnd, int action); int _dw_html_raw(HWND hwnd, char *string); int _dw_html_url(HWND hwnd, char *url); @@ -5402,7 +5695,7 @@ */ void API dw_html_action(HWND handle, int action) { -#if (defined(BUILD_DLL) || defined(BUILD_HTML)) && !defined(__MINGW32__) +#if (defined(BUILD_DLL) || defined(BUILD_HTML)) _dw_html_action(handle, action); #endif } @@ -5418,7 +5711,7 @@ */ int API dw_html_raw(HWND handle, char *string) { -#if (defined(BUILD_DLL) || defined(BUILD_HTML)) && !defined(__MINGW32__) +#if (defined(BUILD_DLL) || defined(BUILD_HTML)) return _dw_html_raw(handle, string); #else return DW_ERROR_GENERAL; @@ -5436,7 +5729,7 @@ */ int API dw_html_url(HWND handle, char *url) { -#if (defined(BUILD_DLL) || defined(BUILD_HTML)) && !defined(__MINGW32__) +#if (defined(BUILD_DLL) || defined(BUILD_HTML)) return _dw_html_url(handle, url); #else return DW_ERROR_GENERAL; @@ -5456,7 +5749,7 @@ WS_CHILD | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); } @@ -5472,6 +5765,7 @@ ULONG flags = 0; HWND tmp; NotebookPage **array = calloc(256, sizeof(NotebookPage *)); + ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); if(!top) flags = TCS_BOTTOM; @@ -5481,9 +5775,12 @@ WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | flags, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); + cinfo->fore = cinfo->back = -1; + cinfo->pOldProc = SubclassWindow(tmp, _simplewndproc); + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); dw_window_set_data(tmp, "_dw_array", (void *)array); dw_window_set_font(tmp, DefaultFont); return tmp; @@ -5660,13 +5957,13 @@ InsertMenuItem(mymenu, 65535, TRUE, &mii); _snprintf(buffer, 30, "_dw_id%ld", id); - dw_window_set_data( DW_HWND_OBJECT, buffer, (void *)mymenu ); + dw_window_set_data( DW_HWND_OBJECT, buffer, DW_POINTER(mymenu) ); _snprintf(buffer, 30, "_dw_checkable%ld", id); - dw_window_set_data( DW_HWND_OBJECT, buffer, (void *)check ); + dw_window_set_data( DW_HWND_OBJECT, buffer, DW_INT_TO_POINTER(check) ); _snprintf(buffer, 30, "_dw_ischecked%ld", id); - dw_window_set_data( DW_HWND_OBJECT, buffer, (void *)is_checked ); + dw_window_set_data( DW_HWND_OBJECT, buffer, DW_INT_TO_POINTER(is_checked) ); _snprintf(buffer, 30, "_dw_isdisabled%ld", id); - dw_window_set_data( DW_HWND_OBJECT, buffer, (void *)is_disabled ); + dw_window_set_data( DW_HWND_OBJECT, buffer, DW_INT_TO_POINTER(is_disabled) ); if (submenu) { @@ -5681,7 +5978,7 @@ if (IsWindow(menux) && !IsMenu((HMENU)menux)) DrawMenuBar(menux); - return (HWND)id; + return (HWND)(uintptr_t)id; } /* @@ -5718,7 +6015,7 @@ * Keep our internal state consistent */ _snprintf( buffer, 30, "_dw_ischecked%ld", id ); - dw_window_set_data( DW_HWND_OBJECT, buffer, (void *)check ); + dw_window_set_data( DW_HWND_OBJECT, buffer, DW_INT_TO_POINTER(check) ); } /* @@ -5741,9 +6038,9 @@ mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu"); _snprintf( buffer1, 30, "_dw_ischecked%ld", id ); - check = (int)dw_window_get_data( DW_HWND_OBJECT, buffer1 ); + check = DW_POINTER_TO_INT(dw_window_get_data( DW_HWND_OBJECT, buffer1 )); _snprintf( buffer2, 30, "_dw_isdisabled%ld", id ); - disabled = (int)dw_window_get_data( DW_HWND_OBJECT, buffer2 ); + disabled = DW_POINTER_TO_INT(dw_window_get_data( DW_HWND_OBJECT, buffer2 )); memset( &mii, 0, sizeof(mii) ); @@ -5810,8 +6107,8 @@ /* * Keep our internal checked state consistent */ - dw_window_set_data( DW_HWND_OBJECT, buffer1, (void *)check ); - dw_window_set_data( DW_HWND_OBJECT, buffer2, (void *)disabled ); + dw_window_set_data( DW_HWND_OBJECT, buffer1, DW_INT_TO_POINTER(check) ); + dw_window_set_data( DW_HWND_OBJECT, buffer2, DW_INT_TO_POINTER(disabled) ); } /* @@ -5834,7 +6131,7 @@ /* If the ID was autogenerated it is safe to remove it */ if(id >= 30000) - dw_signal_disconnect_by_window((HWND)id); + dw_signal_disconnect_by_window((HWND)(uintptr_t)id); /* Make sure the menu is redrawn if needed */ if( (HMENU)menux != mymenu ) @@ -5883,7 +6180,7 @@ WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); @@ -5925,7 +6222,7 @@ WS_BORDER | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); @@ -5989,7 +6286,7 @@ WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); #ifdef AEROGLASS @@ -6018,7 +6315,7 @@ WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); dw_window_set_font(tmp, DefaultFont); @@ -6034,7 +6331,7 @@ { HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, - hrichedit ? RICHEDIT_CLASS : EDITCLASSNAME, + hmsftedit ? MSFTEDIT_CLASS : (hrichedit ? RICHEDIT_CLASS : EDITCLASSNAME), NULL, WS_VISIBLE | WS_BORDER | WS_VSCROLL | ES_MULTILINE | @@ -6042,7 +6339,7 @@ WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); @@ -6053,7 +6350,7 @@ return NULL; } - cinfo->cinfo.pOldProc = SubclassWindow(tmp, _treewndproc); + cinfo->cinfo.pOldProc = SubclassWindow(tmp, _simplewndproc); cinfo->cinfo.fore = cinfo->cinfo.back = -1; cinfo->odd = cinfo->even = DW_RGB_TRANSPARENT; @@ -6078,7 +6375,7 @@ WS_VISIBLE | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); @@ -6107,7 +6404,7 @@ ES_AUTOHSCROLL | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); @@ -6147,7 +6444,7 @@ WS_CLIPCHILDREN | CBS_AUTOHSCROLL | WS_VISIBLE, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); ColorInfo *cinfo = (ColorInfo *)calloc(1, sizeof(ColorInfo)); @@ -6191,7 +6488,7 @@ WS_VISIBLE | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); cinfo->fore = cinfo->back = -1; @@ -6235,7 +6532,7 @@ HIMAGELIST imlist, dimlist; BITMAP bmi = { 0 }; TBBUTTON tbButtons[] = { - { MAKELONG(0, 0), id, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0} + { MAKELONG(0, 0), id, TBSTATE_ENABLED, TBSTYLE_BUTTON} }; /* Get the bitmap from either the icon or bitmap itself */ @@ -6269,8 +6566,8 @@ /* Create the toolbar */ tmp = CreateWindowEx(0L, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | TBSTYLE_AUTOSIZE | CCS_NORESIZE | - CCS_NOPARENTALIGN | CCS_NODIVIDER, 0, 0, 100, 30, DW_HWND_OBJECT, (HMENU)id, DWInstance, NULL); - + CCS_NOPARENTALIGN | CCS_NODIVIDER, 0, 0, 100, 30, DW_HWND_OBJECT, (HMENU)(uintptr_t)id, DWInstance, NULL); + /* Disable visual styles by default */ if(_SetWindowTheme) _SetWindowTheme(tmp, L"", L""); @@ -6281,7 +6578,7 @@ SendMessage(tmp, TB_SETPADDING, 0, 0); SendMessage(tmp, TB_SETIMAGELIST, 0, (LPARAM)imlist); SendMessage(tmp, TB_SETDISABLEDIMAGELIST, 0, (LPARAM)dimlist); - SendMessage(tmp, TB_ADDBUTTONS, 1, (LONG) &tbButtons); + SendMessage(tmp, TB_ADDBUTTONS, 1, (LPARAM) &tbButtons); _create_tooltip(tmp, text); return tmp; @@ -6301,9 +6598,10 @@ HICON icon = LoadImage(DWInstance, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, 0); HBITMAP hbitmap = icon ? 0 : LoadBitmap(DWInstance, MAKEINTRESOURCE(id)); #ifdef TOOLBAR - if(tmp = _create_toolbar(text, id, icon, hbitmap)) + if((tmp = _create_toolbar(text, id, icon, hbitmap))) { cinfo->fore = cinfo->back = -1; + cinfo->pOldProc = SubclassWindow(tmp, _simplewndproc); SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); return tmp; } @@ -6316,7 +6614,7 @@ (icon ? BS_ICON : BS_BITMAP), 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); @@ -6371,9 +6669,10 @@ #endif #ifdef TOOLBAR - if(tmp = _create_toolbar(text, id, hicon, hbitmap)) + if((tmp = _create_toolbar(text, id, hicon, hbitmap))) { cinfo->fore = cinfo->back = -1; + cinfo->pOldProc = SubclassWindow(tmp, _simplewndproc); SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); return tmp; } @@ -6383,7 +6682,7 @@ windowtype | WS_CHILD | BS_PUSHBUTTON | WS_CLIPCHILDREN | WS_VISIBLE, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); @@ -6461,9 +6760,10 @@ } #ifdef TOOLBAR - if(tmp = _create_toolbar(text, id, hicon, hbitmap)) + if((tmp = _create_toolbar(text, id, hicon, hbitmap))) { cinfo->fore = cinfo->back = -1; + cinfo->pOldProc = SubclassWindow(tmp, _simplewndproc); SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); return tmp; } @@ -6475,7 +6775,7 @@ WS_VISIBLE, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL ); @@ -6523,7 +6823,7 @@ UDS_WRAP | UDS_NOTHOUSANDS | WS_VISIBLE, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); @@ -6560,16 +6860,22 @@ */ HWND API dw_radiobutton_new(char *text, ULONG id) { + ColorInfo *cinfo; HWND tmp = CreateWindow(BUTTONCLASSNAME, UTF8toWide(text), WS_CHILD | BS_AUTORADIOBUTTON | WS_CLIPCHILDREN | WS_VISIBLE, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); - ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); + + /* Disable visual styles by default */ + if(_SetWindowTheme) + _SetWindowTheme(tmp, L"", L""); + + cinfo = calloc(1, sizeof(ColorInfo)); cinfo->fore = cinfo->back = -1; cinfo->pOldProc = SubclassWindow(tmp, _BtProc); SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); @@ -6594,7 +6900,7 @@ (vertical ? TBS_VERT : TBS_HORZ), 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); @@ -6603,7 +6909,7 @@ cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc); SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - SendMessage(tmp, TBM_SETRANGE, (WPARAM)FALSE, (LPARAM)MAKELONG(0, increments-1)); + SendMessage(tmp, TBM_SETRANGE, (WPARAM)FALSE, MAKELPARAM(0, increments-1)); return tmp; } @@ -6622,7 +6928,7 @@ (vertical ? SBS_VERT : SBS_HORZ), 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); @@ -6647,7 +6953,7 @@ WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); } @@ -6667,9 +6973,14 @@ BS_TEXT | WS_CLIPCHILDREN | WS_VISIBLE, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); + + /* Disable visual styles by default */ + if(_SetWindowTheme) + _SetWindowTheme(tmp, L"", L""); + cinfo->pOldProc = SubclassWindow(tmp, _BtProc); SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); dw_window_set_data(tmp, "_dw_checkbox", DW_INT_TO_POINTER(1)); @@ -6695,7 +7006,7 @@ WS_VSCROLL | (multi ? LBS_MULTIPLESEL : 0) , 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); @@ -6723,7 +7034,7 @@ */ void API dw_window_set_icon(HWND handle, HICN icon) { - int iicon = (int)icon; + int iicon = DW_POINTER_TO_INT(icon); HICON hicon = iicon < 65536 ? LoadIcon(DWInstance, MAKEINTRESOURCE(iicon)) : (HICON)icon; SendMessage(handle, WM_SETICON, @@ -6731,6 +7042,86 @@ (LPARAM) hicon); } +/* Internal function to set bitmap for the next two functions */ +void _dw_window_set_bitmap(HWND handle, HICON icon, HBITMAP hbitmap) +{ + HBITMAP oldbitmap = 0; + HANDLE oldicon = 0; + TCHAR tmpbuf[100] = {0}; + + if (!icon && !hbitmap) + return; + + GetClassName(handle, tmpbuf, 99); + + if(_tcsnicmp(tmpbuf, BUTTONCLASSNAME, _tcslen(BUTTONCLASSNAME)+1)==0) + { + oldbitmap = (HBITMAP)SendMessage(handle, BM_GETIMAGE, IMAGE_BITMAP, 0); + oldicon = (HICON)SendMessage(handle, BM_GETIMAGE, IMAGE_ICON, 0); + SendMessage(handle, BM_SETIMAGE, + (icon ? (WPARAM)IMAGE_ICON : (WPARAM)IMAGE_BITMAP), + (icon ? (LPARAM)icon : (LPARAM)hbitmap)); + } +#ifdef TOOLBAR + /* Bitmap Buttons */ + else if(_tcsnicmp(tmpbuf, TOOLBARCLASSNAME, _tcslen(TOOLBARCLASSNAME)+1) == 0) + { + HIMAGELIST imlist = (HIMAGELIST)SendMessage(handle, TB_GETIMAGELIST, 0, 0); + HIMAGELIST dimlist = (HIMAGELIST)SendMessage(handle, TB_GETDISABLEDIMAGELIST, 0, 0); + BITMAP bmi = { 0 }; + + if(hbitmap) + { + GetObject(hbitmap, sizeof(BITMAP), &bmi); + ImageList_Replace(imlist, 0, hbitmap, NULL); + _to_grayscale(hbitmap, bmi.bmWidth, bmi.bmHeight); + ImageList_Replace(dimlist, 0, hbitmap, NULL); + DeleteObject(hbitmap); + } + else if(icon) + { + ICONINFO iconinfo; + + GetIconInfo(icon, &iconinfo); + GetObject(iconinfo.hbmColor, sizeof(BITMAP), &bmi); + ImageList_ReplaceIcon(imlist, 0, icon); + _to_grayscale(iconinfo.hbmColor, bmi.bmWidth, bmi.bmHeight); + ImageList_Replace(dimlist, 0, iconinfo.hbmColor, iconinfo.hbmMask); + DeleteObject(iconinfo.hbmColor); + DeleteObject(iconinfo.hbmMask); + DestroyIcon(icon); + } + InvalidateRect(handle, NULL, FALSE); + } +#endif + else + { + oldbitmap = (HBITMAP)SendMessage(handle, STM_GETIMAGE, IMAGE_BITMAP, 0); + oldicon = (HICON)SendMessage(handle, STM_GETIMAGE, IMAGE_ICON, 0); + SendMessage(handle, STM_SETIMAGE, + (icon ? (WPARAM)IMAGE_ICON : (WPARAM)IMAGE_BITMAP), + (icon ? (LPARAM)icon : (LPARAM)hbitmap)); + } + + if(oldbitmap) + DeleteObject(oldbitmap); + if(oldicon) + DeleteObject(oldicon); + + /* If we changed the bitmap... */ + { + Item *item = _box_item(handle); + + /* Check to see if any of the sizes need to be recalculated */ + if(item && (item->origwidth == -1 || item->origheight == -1)) + { + _control_size(handle, item->origwidth == -1 ? &item->width : NULL, item->origheight == -1 ? &item->height : NULL); + /* Queue a redraw on the top-level window */ + _dw_redraw(_toplevel_window(handle), TRUE); + } + } +} + /* * Sets the bitmap used for a given static window. * Parameters: @@ -6744,9 +7135,7 @@ void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename) { HBITMAP hbitmap = 0; - HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, STM_GETIMAGE, IMAGE_BITMAP, 0); HANDLE icon = 0; - HANDLE oldicon = (HICON)SendMessage(handle, STM_GETIMAGE, IMAGE_ICON, 0); if(id) { @@ -6760,46 +7149,9 @@ #else _dw_get_image_handle(filename, &icon, &hbitmap); #endif - if (icon == 0 && hbitmap == 0) - return; - } - - if(icon) - { - SendMessage(handle, BM_SETIMAGE, - (WPARAM) IMAGE_ICON, - (LPARAM) icon); - SendMessage(handle, STM_SETIMAGE, - (WPARAM) IMAGE_ICON, - (LPARAM) icon); - } - else if(hbitmap) - { - SendMessage(handle, BM_SETIMAGE, - (WPARAM) IMAGE_BITMAP, - (LPARAM) hbitmap); - SendMessage(handle, STM_SETIMAGE, - (WPARAM) IMAGE_BITMAP, - (LPARAM) hbitmap); - } - - if(hbitmap && oldbitmap) - DeleteObject(oldbitmap); - else if(icon && oldicon) - DeleteObject(oldicon); - - /* If we changed the bitmap... */ - { - Item *item = _box_item(handle); - - /* Check to see if any of the sizes need to be recalculated */ - if(item && (item->origwidth == -1 || item->origheight == -1)) - { - _control_size(handle, item->origwidth == -1 ? &item->width : NULL, item->origheight == -1 ? &item->height : NULL); - /* Queue a redraw on the top-level window */ - _dw_redraw(_toplevel_window(handle), TRUE); - } - } + } + + _dw_window_set_bitmap(handle, icon, hbitmap); } /* @@ -6816,9 +7168,7 @@ void API dw_window_set_bitmap_from_data(HWND handle, unsigned long id, char *data, int len) { HBITMAP hbitmap=0; - HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, STM_GETIMAGE, IMAGE_BITMAP, 0); HICON icon=0; - HICON oldicon = (HICON)SendMessage(handle, STM_GETIMAGE, IMAGE_ICON, 0); char *file; FILE *fp; @@ -6859,29 +7209,7 @@ icon = LoadImage( DWInstance, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_SHARED ); } - if ( icon ) - { - SendMessage( handle, BM_SETIMAGE, - (WPARAM) IMAGE_ICON, - (LPARAM) icon ); - SendMessage( handle, STM_SETIMAGE, - (WPARAM) IMAGE_ICON, - (LPARAM) icon ); - } - else if ( hbitmap ) - { - SendMessage( handle, BM_SETIMAGE, - (WPARAM) IMAGE_BITMAP, - (LPARAM) hbitmap ); - SendMessage( handle, STM_SETIMAGE, - (WPARAM) IMAGE_BITMAP, - (LPARAM) hbitmap ); - } - - if( hbitmap && oldbitmap ) - DeleteObject( oldbitmap ); - else if ( icon && oldicon ) - DeleteObject( oldicon ); + _dw_window_set_bitmap(handle, icon, hbitmap); } @@ -7008,7 +7336,7 @@ { char buffer[31] = {0}; HMENU mymenu; - ULONG id = (ULONG)handle; + ULONG id = (ULONG)(uintptr_t)handle; _snprintf(buffer, 30, "_dw_id%ld", id); mymenu = (HMENU)dw_window_get_data(DW_HWND_OBJECT, buffer); @@ -7031,7 +7359,7 @@ { char buffer[31] = {0}; HMENU mymenu; - ULONG id = (ULONG)handle; + ULONG id = (ULONG)(uintptr_t)handle; _snprintf(buffer, 30, "_dw_id%ld", id); mymenu = (HMENU)dw_window_get_data(DW_HWND_OBJECT, buffer); @@ -7169,6 +7497,9 @@ thisbox->count++; +#ifdef AEROGLASS + AllowDarkModeForWindow(item, _DW_DARK_MODE_ENABLED); +#endif SetParent(item, box); if(_tcsnicmp(tmpbuf, UPDOWN_CLASS, _tcslen(UPDOWN_CLASS)+1)==0) { @@ -7662,7 +7993,7 @@ { char buffer[31] = {0}; HMENU mymenu; - ULONG id = (ULONG)handle; + ULONG id = (ULONG)(uintptr_t)handle; _snprintf(buffer, 30, "_dw_id%ld", id); mymenu = (HMENU)dw_window_get_data(DW_HWND_OBJECT, buffer); @@ -7700,7 +8031,10 @@ tmp ^= mask; tmp |= style & mask; - if(_tcsnicmp(tmpbuf, ClassName, _tcslen(ClassName)+1)==0) + /* Drop out for status bar, it currently doesn't accept styles on Windows */ + if(_tcsnicmp(tmpbuf, StatusbarClassName, _tcslen(StatusbarClassName)+1)==0) + return; + else if(_tcsnicmp(tmpbuf, ClassName, _tcslen(ClassName)+1)==0) { tmp = tmp & 0xffff0000; #ifdef AEROGLASS @@ -7730,7 +8064,6 @@ } else if(_tcsnicmp(tmpbuf, STATICCLASSNAME, _tcslen(STATICCLASSNAME)+1)==0) { - static ULONG halign = (SS_LEFTNOWORDWRAP | SS_RIGHT | SS_CENTER); ULONG thismask = mask & ~(DW_DT_VCENTER | DW_DT_WORDBREAK); ULONG thisstyle = style & ~(DW_DT_VCENTER | DW_DT_WORDBREAK); ULONG type = style & mask & 0xFL; @@ -8469,7 +8802,7 @@ else dw_window_set_style(handle, ES_AUTOHSCROLL, ES_AUTOHSCROLL); /* If it is a rich edit control use the rich edit message */ - if(hrichedit) + if(hrichedit || hmsftedit) { if(state) SendMessage(handle, EM_SETOPTIONS, (WPARAM)ECOOP_AND, (LPARAM)~ECO_AUTOHSCROLL); @@ -8479,6 +8812,16 @@ } /* + * Sets the word auto complete state of an MLE box. + * Parameters: + * handle: Handle to the MLE. + * state: Bitwise combination of DW_MLE_COMPLETE_TEXT/DASH/QUOTE + */ +void API dw_mle_set_auto_complete(HWND handle, int state) +{ +} + +/* * Sets the current cursor position of an MLE box. * Parameters: * handle: Handle to the MLE to be positioned. @@ -8486,7 +8829,7 @@ */ void API dw_mle_set_cursor(HWND handle, int point) { - SendMessage(handle, EM_SETSEL, 0, MAKELONG(point,point)); + SendMessage(handle, EM_SETSEL, 0, MAKELPARAM(point,point)); SendMessage(handle, EM_SCROLLCARET, 0, 0); } @@ -8645,7 +8988,7 @@ */ void API dw_scrollbar_set_pos(HWND handle, unsigned int position) { - dw_window_set_data(handle, "_dw_scrollbar_value", (void *)position); + dw_window_set_data(handle, "_dw_scrollbar_value", DW_UINT_TO_POINTER(position)); SendMessage(handle, SBM_SETPOS, (WPARAM)position, (LPARAM)TRUE); } @@ -8779,14 +9122,10 @@ TVITEM tvi; TVINSERTSTRUCT tvins; HTREEITEM hti; - void **ptrs= malloc(sizeof(void *) * 2); - - ptrs[0] = title; - ptrs[1] = itemdata; tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; tvi.pszText = UTF8toWide(title); - tvi.lParam = (LONG)ptrs; + tvi.lParam = (LPARAM)itemdata; tvi.cchTextMax = (int)_tcslen(tvi.pszText); tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1); @@ -8813,14 +9152,10 @@ TVITEM tvi; TVINSERTSTRUCT tvins; HTREEITEM hti; - void **ptrs= malloc(sizeof(void *) * 2); - - ptrs[0] = title; - ptrs[1] = itemdata; tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; tvi.pszText = UTF8toWide(title); - tvi.lParam = (LONG)ptrs; + tvi.lParam = (LPARAM)itemdata; tvi.cchTextMax = (int)_tcslen(tvi.pszText); tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1); @@ -8844,17 +9179,12 @@ void API dw_tree_item_change(HWND handle, HTREEITEM item, char *title, HICN icon) { TVITEM tvi; - void **ptrs; tvi.mask = TVIF_HANDLE; tvi.hItem = item; if(TreeView_GetItem(handle, &tvi)) { - - ptrs = (void **)tvi.lParam; - ptrs[0] = title; - tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvi.pszText = UTF8toWide(title); tvi.cchTextMax = (int)_tcslen(tvi.pszText); @@ -8875,16 +9205,12 @@ void API dw_tree_item_set_data(HWND handle, HTREEITEM item, void *itemdata) { TVITEM tvi; - void **ptrs; - - tvi.mask = TVIF_HANDLE; + + tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = item; - - if(TreeView_GetItem(handle, &tvi)) - { - ptrs = (void **)tvi.lParam; - ptrs[1] = itemdata; - } + tvi.lParam = (LPARAM)itemdata; + + TreeView_SetItem(handle, &tvi); } /* @@ -8896,15 +9222,13 @@ void * API dw_tree_item_get_data(HWND handle, HTREEITEM item) { TVITEM tvi; - void **ptrs; tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = item; if(TreeView_GetItem(handle, &tvi)) { - ptrs = (void **)tvi.lParam; - return ptrs[1]; + return (void *)tvi.lParam; } return NULL; } @@ -8918,12 +9242,15 @@ char * API dw_tree_get_title(HWND handle, HTREEITEM item) { TVITEM tvi; - - tvi.mask = TVIF_HANDLE; + TCHAR textbuf[1025] = {0}, *textptr = textbuf; + + tvi.mask = TVIF_HANDLE | TVIF_TEXT; tvi.hItem = item; + tvi.pszText = textptr; + tvi.cchTextMax = 1024; if(TreeView_GetItem(handle, &tvi)) - return _strdup(WideToUTF8(tvi.pszText)); + return _strdup(WideToUTF8(textptr)); return NULL; } @@ -8949,22 +9276,6 @@ TreeView_SelectItem(handle, item); } -/* Delete all tree subitems */ -void _dw_tree_item_delete_recursive(HWND handle, HTREEITEM node) -{ - HTREEITEM hti; - - hti = TreeView_GetChild(handle, node); - - while(hti) - { - HTREEITEM lastitem = hti; - - hti = TreeView_GetNextSibling(handle, hti); - dw_tree_item_delete(handle, lastitem); - } -} - /* * Removes all nodes from a tree. * Parameters: @@ -8972,18 +9283,9 @@ */ void API dw_tree_clear(HWND handle) { - HTREEITEM hti = TreeView_GetRoot(handle); - - dw_window_set_data(handle, "_dw_select_item", (void *)1); - while(hti) - { - HTREEITEM lastitem = hti; - - _dw_tree_item_delete_recursive(handle, hti); - hti = TreeView_GetNextSibling(handle, hti); - dw_tree_item_delete(handle, lastitem); - } - dw_window_set_data(handle, "_dw_select_item", (void *)0); + dw_window_set_data(handle, "_dw_select_item", DW_INT_TO_POINTER(1)); + TreeView_DeleteAllItems(handle); + dw_window_set_data(handle, "_dw_select_item", NULL); } /* @@ -9016,22 +9318,7 @@ */ void API dw_tree_item_delete(HWND handle, HTREEITEM item) { - TVITEM tvi; - void **ptrs=NULL; - - if(item == TVI_ROOT || !item) - return; - - tvi.mask = TVIF_HANDLE; - tvi.hItem = item; - - if(TreeView_GetItem(handle, &tvi)) - ptrs = (void **)tvi.lParam; - - _dw_tree_item_delete_recursive(handle, item); TreeView_DeleteItem(handle, item); - if(ptrs) - free(ptrs); } /* @@ -9254,7 +9541,7 @@ item = ListView_InsertItem(handle, &lvi); for(z=1;z<rowcount;z++) ListView_InsertItem(handle, &lvi); - dw_window_set_data(handle, "_dw_insertitem", (void *)item); + dw_window_set_data(handle, "_dw_insertitem", DW_INT_TO_POINTER(item)); return (void *)handle; } @@ -9265,7 +9552,6 @@ { int z; static HWND lasthwnd = NULL; - HIMAGELIST himl; /* We can't add an invalid handle */ if(!hicon) @@ -9285,12 +9571,12 @@ ImageList_AddIcon(hLarge, hicon); if(type) { - himl = TreeView_SetImageList(handle, hSmall, TVSIL_NORMAL); + TreeView_SetImageList(handle, hSmall, TVSIL_NORMAL); } else { - himl = ListView_SetImageList(handle, hSmall, LVSIL_SMALL); - himl = ListView_SetImageList(handle, hLarge, LVSIL_NORMAL); + ListView_SetImageList(handle, hSmall, LVSIL_SMALL); + ListView_SetImageList(handle, hLarge, LVSIL_NORMAL); } lasthwnd = handle; return z; @@ -9302,12 +9588,12 @@ { if(type) { - himl = TreeView_SetImageList(handle, hSmall, TVSIL_NORMAL); + TreeView_SetImageList(handle, hSmall, TVSIL_NORMAL); } else { - himl = ListView_SetImageList(handle, hSmall, LVSIL_SMALL); - himl = ListView_SetImageList(handle, hLarge, LVSIL_NORMAL); + ListView_SetImageList(handle, hSmall, LVSIL_SMALL); + ListView_SetImageList(handle, hLarge, LVSIL_NORMAL); } lasthwnd = handle; } @@ -9333,7 +9619,7 @@ if(pointer) { - item = (int)dw_window_get_data(handle, "_dw_insertitem"); + item = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_insertitem")); } lvi.iItem = row + item; @@ -9379,7 +9665,7 @@ if(pointer) { - item = (int)dw_window_get_data(handle, "_dw_insertitem"); + item = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_insertitem")); } if(!cinfo || !cinfo->flags) @@ -9557,25 +9843,14 @@ void API dw_container_set_stripe(HWND handle, unsigned long oddcolor, unsigned long evencolor) { ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - unsigned long temp = _internal_color(oddcolor); - COLORREF even, odd = RGB(DW_RED_VALUE(temp), DW_GREEN_VALUE(temp), DW_BLUE_VALUE(temp)); - temp = _internal_color(evencolor); - even = RGB(DW_RED_VALUE(temp), DW_GREEN_VALUE(temp), DW_BLUE_VALUE(temp)); /* Drop out on error */ if(!cinfo) return; /* Create new brushes or remove if transparent */ - if(oddcolor != DW_RGB_TRANSPARENT) - cinfo->odd = (oddcolor == DW_CLR_DEFAULT ? RGB(230, 230, 230) : odd); - else - cinfo->odd = oddcolor; - - if(evencolor != DW_RGB_TRANSPARENT) - cinfo->even = (evencolor == DW_CLR_DEFAULT ? DW_RGB_TRANSPARENT : even); - else - cinfo->even = evencolor; + cinfo->odd = oddcolor; + cinfo->even = evencolor; } /* @@ -9591,24 +9866,51 @@ } /* Internal version that handles both types */ -void _dw_container_set_row_title(HWND handle, void *pointer, int row, char *title) +void _dw_container_set_row_data(HWND handle, void *pointer, int row, int type, void *data) { LV_ITEM lvi; int item = 0; if(pointer) { - item = (int)dw_window_get_data(handle, "_dw_insertitem"); - } - + item = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_insertitem")); + } + + memset(&lvi, 0, sizeof(LV_ITEM)); + lvi.iItem = row + item; - lvi.iSubItem = 0; lvi.mask = LVIF_PARAM; - lvi.lParam = (LPARAM)title; - - if(!ListView_SetItem(handle, &lvi) && lvi.lParam) - lvi.lParam = 0; - + + if(ListView_GetItem(handle, &lvi)) + { + void **params = (void **)lvi.lParam; + void *newparam = data; + + /* Make sure we have our pointer array... */ + if(!params) + { + /* If not allocate it */ + params = (void **)calloc(2, sizeof(void *)); + lvi.lParam = (LPARAM)params; + ListView_SetItem(handle, &lvi); + } + /* If type string, we need to duplicate the string... + * freeing any existing string. + */ + if(type == _DW_DATA_TYPE_STRING) + { + void *oldparam = params[type]; + + params[type] = NULL; + + if(oldparam) + free(oldparam); + if(newparam) + newparam = _strdup((char *)newparam); + } + /* Set the new data in the pointer array */ + params[type] = newparam; + } } /* @@ -9620,7 +9922,7 @@ */ void API dw_container_set_row_title(void *pointer, int row, char *title) { - _dw_container_set_row_title(pointer, pointer, row, title); + _dw_container_set_row_data(pointer, pointer, row, _DW_DATA_TYPE_STRING, title); } /* @@ -9632,7 +9934,31 @@ */ void API dw_container_change_row_title(HWND handle, int row, char *title) { - _dw_container_set_row_title(handle, NULL, row, title); + _dw_container_set_row_data(handle, NULL, row, _DW_DATA_TYPE_STRING, title); +} + +/* + * Sets the data of a row in the container. + * Parameters: + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * row: Zero based row of data being set. + * data: Data pointer. + */ +void API dw_container_set_row_data(void *pointer, int row, void *data) +{ + _dw_container_set_row_data(pointer, pointer, row, _DW_DATA_TYPE_POINTER, data); +} + +/* + * Changes the data of a row already inserted in the container. + * Parameters: + * handle: Handle to the container window (widget). + * row: Zero based row of data being set. + * data: Data pointer. + */ +void API dw_container_change_row_data(HWND handle, int row, void *data) +{ + _dw_container_set_row_data(handle, NULL, row, _DW_DATA_TYPE_POINTER, data); } /* @@ -9666,7 +9992,7 @@ */ void API dw_container_delete(HWND handle, int rowcount) { - int z, _index = (int)dw_window_get_data(handle, "_dw_index"); + int z, _index = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_index")); for(z=0;z<rowcount;z++) { @@ -9675,7 +10001,7 @@ if(rowcount > _index) dw_window_set_data(handle, "_dw_index", 0); else - dw_window_set_data(handle, "_dw_index", (void *)(_index - rowcount)); + dw_window_set_data(handle, "_dw_index", DW_INT_TO_POINTER((_index - rowcount))); } /* @@ -9711,9 +10037,15 @@ { LV_ITEM lvi; int _index = ListView_GetNextItem(handle, -1, flags); + void **params; + int type = _DW_DATA_TYPE_STRING; + char *retval = NULL; if(_index == -1) - return NULL; + return retval; + + if(flags & DW_CR_RETDATA) + type = _DW_DATA_TYPE_POINTER; memset(&lvi, 0, sizeof(LV_ITEM)); @@ -9721,9 +10053,18 @@ lvi.mask = LVIF_PARAM; ListView_GetItem(handle, &lvi); - - dw_window_set_data(handle, "_dw_index", (void *)_index); - return (char *)lvi.lParam; + params = (void **)lvi.lParam; + + if(params) + { + if(type == _DW_DATA_TYPE_STRING && params[type]) + retval = _strdup((char *)params[type]); + else + retval = (char *)params[type]; + } + + dw_window_set_data(handle, "_dw_index", DW_INT_TO_POINTER(_index)); + return retval; } /* @@ -9737,22 +10078,37 @@ char * API dw_container_query_next(HWND handle, unsigned long flags) { LV_ITEM lvi; - int _index = (int)dw_window_get_data(handle, "_dw_index"); + int _index = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_index")); + void **params; + int type = _DW_DATA_TYPE_STRING; + char *retval = NULL; _index = ListView_GetNextItem(handle, _index, flags); if(_index == -1) - return NULL; - + return retval; + + if(flags & DW_CR_RETDATA) + type = _DW_DATA_TYPE_POINTER; + memset(&lvi, 0, sizeof(LV_ITEM)); lvi.iItem = _index; lvi.mask = LVIF_PARAM; ListView_GetItem(handle, &lvi); - - dw_window_set_data(handle, "_dw_index", (void *)_index); - return (char *)lvi.lParam; + params = (void **)lvi.lParam; + + if(params) + { + if(type == _DW_DATA_TYPE_STRING && params[type]) + retval = _strdup((char *)params[type]); + else + retval = (char *)params[type]; + } + + dw_window_set_data(handle, "_dw_index", DW_INT_TO_POINTER(_index)); + return retval; } /* @@ -9764,11 +10120,11 @@ void API dw_container_cursor(HWND handle, char *text) { int index = ListView_GetNextItem(handle, -1, LVNI_ALL); - int textcomp = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_textcomp")); while ( index != -1 ) { LV_ITEM lvi; + void **params; memset(&lvi, 0, sizeof(LV_ITEM)); @@ -9776,8 +10132,48 @@ lvi.mask = LVIF_PARAM; ListView_GetItem( handle, &lvi ); - - if ( (textcomp && lvi.lParam && strcmp( (char *)lvi.lParam, text ) == 0) || (!textcomp && (char *)lvi.lParam == text) ) + params = (void **)lvi.lParam; + + if ( params && params[_DW_DATA_TYPE_STRING] && strcmp( (char *)params[_DW_DATA_TYPE_STRING], text ) == 0 ) + { + unsigned long width, height; + + ListView_SetItemState( handle, index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED ); + dw_window_get_pos_size( handle, NULL, NULL, &width, &height); + if(width < 10 || height < 10) + dw_window_set_data( handle, "_dw_cursor", DW_INT_TO_POINTER(index) ); + ListView_EnsureVisible( handle, index, TRUE ); + return; + } + + index = ListView_GetNextItem( handle, index, LVNI_ALL ); + } +} + +/* + * Cursors the item with the text speficied, and scrolls to that item. + * Parameters: + * handle: Handle to the window (widget) to be queried. + * text: Text usually returned by dw_container_query(). + */ +void API dw_container_cursor_by_data(HWND handle, void *data) +{ + int index = ListView_GetNextItem(handle, -1, LVNI_ALL); + + while ( index != -1 ) + { + LV_ITEM lvi; + void **params; + + memset(&lvi, 0, sizeof(LV_ITEM)); + + lvi.iItem = index; + lvi.mask = LVIF_PARAM; + + ListView_GetItem( handle, &lvi ); + params = (void **)lvi.lParam; + + if ( params && params[_DW_DATA_TYPE_POINTER] == data ) { unsigned long width, height; @@ -9802,11 +10198,11 @@ void API dw_container_delete_row(HWND handle, char *text) { int index = ListView_GetNextItem(handle, -1, LVNI_ALL); - int textcomp = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_textcomp")); while(index != -1) { LV_ITEM lvi; + void **params; memset(&lvi, 0, sizeof(LV_ITEM)); @@ -9814,19 +10210,58 @@ lvi.mask = LVIF_PARAM; ListView_GetItem(handle, &lvi); - - if ( (textcomp && lvi.lParam && strcmp( (char *)lvi.lParam, text ) == 0) || (!textcomp && (char *)lvi.lParam == text) ) - { - int _index = (int)dw_window_get_data(handle, "_dw_index"); + params = (void **)lvi.lParam; + + if ( params && params[_DW_DATA_TYPE_STRING] && strcmp( (char *)params[_DW_DATA_TYPE_STRING], text ) == 0 ) + { + int _index = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_index")); if(index < _index) - dw_window_set_data(handle, "_dw_index", (void *)(_index - 1)); + dw_window_set_data(handle, "_dw_index", DW_INT_TO_POINTER((_index - 1))); ListView_DeleteItem(handle, index); return; } - index = ListView_GetNextItem(handle, index, LVNI_ALL); + index = ListView_GetNextItem(handle, index, LVNI_ALL); + } +} + +/* + * Deletes the item with the text speficied. + * Parameters: + * handle: Handle to the window (widget). + * text: Text usually returned by dw_container_query(). + */ +void API dw_container_delete_row_by_data(HWND handle, void *data) +{ + int index = ListView_GetNextItem(handle, -1, LVNI_ALL); + + while(index != -1) + { + LV_ITEM lvi; + void **params; + + memset(&lvi, 0, sizeof(LV_ITEM)); + + lvi.iItem = index; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(handle, &lvi); + params = (void **)lvi.lParam; + + if ( params && params[_DW_DATA_TYPE_POINTER] == data ) + { + int _index = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_index")); + + if(index < _index) + dw_window_set_data(handle, "_dw_index", DW_INT_TO_POINTER((_index - 1))); + + ListView_DeleteItem(handle, index); + return; + } + + index = ListView_GetNextItem(handle, index, LVNI_ALL); } } @@ -9918,7 +10353,7 @@ tnid.cbSize = sizeof(NOTIFYICONDATA); tnid.hWnd = handle; - tnid.uID = (UINT)icon; + tnid.uID = (UINT)(uintptr_t)icon; tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; tnid.uCallbackMessage = WM_USER+2; tnid.hIcon = (HICON)icon; @@ -9942,7 +10377,7 @@ tnid.cbSize = sizeof(NOTIFYICONDATA); tnid.hWnd = handle; - tnid.uID = (UINT)icon; + tnid.uID = (UINT)(uintptr_t)icon; Shell_NotifyIcon(NIM_DELETE, &tnid); } @@ -9962,7 +10397,7 @@ WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); newbox->pad = 0; @@ -10005,7 +10440,7 @@ DeleteObject(hPen); DeleteObject(hBrush); - TlsSetValue(_foreground, (LPVOID)foreground); + TlsSetValue(_foreground, (LPVOID)(uintptr_t)foreground); TlsSetValue(_hPen, CreatePen(PS_SOLID, 1, foreground)); TlsSetValue(_hBrush, CreateSolidBrush(foreground)); } @@ -10026,7 +10461,7 @@ if(value == DW_RGB_TRANSPARENT) TlsSetValue(_background, (LPVOID)DW_RGB_TRANSPARENT); else - TlsSetValue(_background, (LPVOID)background); + TlsSetValue(_background, (LPVOID)(uintptr_t)background); } /* Allows the user to choose a color using the system's color chooser dialog. @@ -10468,10 +10903,10 @@ mustdelete = 1; } - background = (COLORREF)TlsGetValue(_background); + background = (COLORREF)(uintptr_t)TlsGetValue(_background); if(hFont) oldFont = SelectObject(hdc, hFont); - SetTextColor(hdc, (COLORREF)TlsGetValue(_foreground)); + SetTextColor(hdc, (COLORREF)(uintptr_t)TlsGetValue(_foreground)); if(background == DW_RGB_TRANSPARENT) SetBkMode(hdc, TRANSPARENT); else @@ -11288,7 +11723,7 @@ sa.lpSecurityDescriptor = &_dwsd; sa.bInheritHandle = FALSE; - handle = CreateFileMapping((HANDLE)0xFFFFFFFF, &sa, PAGE_READWRITE, 0, size, UTF8toWide(name)); + handle = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, size, UTF8toWide(name)); if(!handle) return 0; @@ -11342,13 +11777,40 @@ return 0; } -/* - * Encapsulate thread creation on Win32. - */ -void _dwthreadstart(void *data) -{ - void (* threadfunc)(void *) = NULL; - void **tmp = (void **)data; +/* + * Generally an internal function called from a newly created + * thread to setup the Dynamic Windows environment for the thread. + * However it is exported so language bindings can call it when + * they create threads that require access to Dynamic Windows. + */ +void API _dw_init_thread(void) +{ + COLORREF foreground = RGB(128,128,128); + COLORREF background = DW_RGB_TRANSPARENT; +#ifdef GDIPLUS + ARGB gpfore = MAKEARGB(255, 128, 128, 128); + GpBrush *brush; + GpPen *pen; + + GdipCreatePen1(gpfore, 1.0, UnitPixel, &pen); + TlsSetValue(_gpPen, (LPVOID)pen); + GdipCreateSolidFill(gpfore, &brush); + TlsSetValue(_gpBrush, brush); +#endif + TlsSetValue(_foreground, DW_UINT_TO_POINTER(foreground)); + TlsSetValue(_background, DW_UINT_TO_POINTER(background)); + TlsSetValue(_hPen, CreatePen(PS_SOLID, 1, foreground)); + TlsSetValue(_hBrush, CreateSolidBrush(foreground)); +} + +/* + * Generally an internal function called from a terminating + * thread to cleanup the Dynamic Windows environment for the thread. + * However it is exported so language bindings can call it when + * they exit threads that require access to Dynamic Windows. + */ +void API _dw_deinit_thread(void) +{ HPEN hPen; HBRUSH hBrush; #ifdef GDIPLUS @@ -11356,12 +11818,6 @@ GpPen *pen; #endif - _init_thread(); - - threadfunc = (void (*)(void *))tmp[0]; - threadfunc(tmp[1]); - - free(tmp); if((hPen = TlsGetValue(_hPen))) DeleteObject(hPen); if((hBrush = TlsGetValue(_hBrush))) @@ -11375,6 +11831,23 @@ } /* + * Encapsulate thread creation on Win32. + */ +void _dwthreadstart(void *data) +{ + void (* threadfunc)(void *) = NULL; + void **tmp = (void **)data; + + _dw_init_thread(); + + threadfunc = (void (*)(void *))tmp[0]; + threadfunc(tmp[1]); + + free(tmp); + _dw_deinit_thread(); +} + +/* * Creates a new thread with a starting point of func. * Parameters: * func: Function which will be run in the new thread. @@ -11401,6 +11874,7 @@ void API dw_thread_end(void) { #if !defined(__CYGWIN__) + _dw_deinit_thread(); _endthread(); #endif } @@ -11419,10 +11893,8 @@ /* * Cleanly terminates a DW session, should be signal handler safe. - * Parameters: - * exitcode: Exit code reported to the operating system. - */ -void API dw_exit(int exitcode) + */ +void API dw_shutdown(void) { OleUninitialize(); #ifdef AEROGLASS @@ -11431,6 +11903,16 @@ #endif FreeLibrary(huxtheme); DestroyWindow(hwndTooltip); +} + +/* + * Cleanly terminates a DW session, should be signal handler safe. + * Parameters: + * exitcode: Exit code reported to the operating system. + */ +void API dw_exit(int exitcode) +{ + dw_shutdown(); exit(exitcode); } @@ -11450,26 +11932,26 @@ WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); if(tmp) { HWND tmpbox = dw_box_new(DW_VERT, 0); - float *percent = (float *)malloc(sizeof(float)); + float *percent = (float *)malloc(sizeof(float)); dw_box_pack_start(tmpbox, topleft, 1, 1, TRUE, TRUE, 0); SetParent(tmpbox, tmp); - dw_window_set_data(tmp, "_dw_topleft", (void *)tmpbox); + dw_window_set_data(tmp, "_dw_topleft", DW_POINTER(tmpbox)); tmpbox = dw_box_new(DW_VERT, 0); dw_box_pack_start(tmpbox, bottomright, 1, 1, TRUE, TRUE, 0); SetParent(tmpbox, tmp); - dw_window_set_data(tmp, "_dw_bottomright", (void *)tmpbox); + dw_window_set_data(tmp, "_dw_bottomright", DW_POINTER(tmpbox)); *percent = 50.0; - dw_window_set_data(tmp, "_dw_percent", (void *)percent); - dw_window_set_data(tmp, "_dw_type", (void *)type); + dw_window_set_data(tmp, "_dw_percent", DW_POINTER(percent)); + dw_window_set_data(tmp, "_dw_type", DW_INT_TO_POINTER(type)); } return tmp; } @@ -11482,8 +11964,8 @@ void API dw_splitbar_set(HWND handle, float percent) { float *mypercent = (float *)dw_window_get_data(handle, "_dw_percent"); - int type = (int)dw_window_get_data(handle, "_dw_type"); - unsigned long width, height; + int type = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_type")); + unsigned long width, height; if(mypercent) *mypercent = percent; @@ -11528,7 +12010,7 @@ WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | MCS_DAYSTATE, 0,0,0,0, DW_HWND_OBJECT, - (HMENU)id, + (HMENU)(uintptr_t)id, DWInstance, NULL); if ( tmp ) @@ -11760,6 +12242,8 @@ strcpy(env->osName, "Windows 7"); else if(env->MajorVersion == 6 && env->MinorVersion > 1) strcpy(env->osName, "Windows 8"); + else if(env->MajorVersion == 10) + strcpy(env->osName, "Windows 10"); else strcpy(env->osName, "Windows NT"); @@ -11947,10 +12431,15 @@ for(z=0;z<count;z++) { - newparams[z] = malloc(strlen(params[z])+3); - strcpy(newparams[z], "\""); - strcat(newparams[z], params[z]); - strcat(newparams[z], "\""); + if(strchr(params[z], ' ')) + { + newparams[z] = malloc(strlen(params[z])+3); + strcpy(newparams[z], "\""); + strcat(newparams[z], params[z]); + strcat(newparams[z], "\""); + } + else + newparams[z] = strdup(params[z]); } newparams[count] = NULL; @@ -11992,7 +12481,7 @@ } } - retcode = (int)ShellExecute(NULL, TEXT("open"), UTF8toWide(browseurl), NULL, NULL, SW_SHOWNORMAL); + retcode = DW_POINTER_TO_INT(ShellExecute(NULL, TEXT("open"), UTF8toWide(browseurl), NULL, NULL, SW_SHOWNORMAL)); if(retcode<33 && retcode != 2) return DW_ERROR_UNKNOWN; return DW_ERROR_NONE; @@ -12002,7 +12491,7 @@ { PRINTDLG pd; DOCINFO di; - int (*drawfunc)(HPRINT, HPIXMAP, int, void *); + int (DWSIGNAL *drawfunc)(HPRINT, HPIXMAP, int, void *); void *drawdata; unsigned long flags; } DWPrint; @@ -12340,7 +12829,7 @@ if(timerid) { - _new_signal(WM_TIMER, NULL, timerid, sigfunc, data); + _new_signal(WM_TIMER, NULL, timerid, sigfunc, NULL, data); return timerid; } } @@ -12397,6 +12886,20 @@ */ void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data) { + dw_signal_connect_data(window, signame, sigfunc, NULL, data); +} + +/* + * Add a callback to a window event with a closure callback. + * Parameters: + * window: Window handle of signal to be called back. + * signame: A string pointer identifying which signal to be hooked. + * sigfunc: The pointer to the function to be used as the callback. + * discfunc: The pointer to the function called when this handler is removed. + * data: User data to be passed to the handler function. + */ +void API dw_signal_connect_data(HWND window, char *signame, void *sigfunc, void *discfunc, void *data) +{ ULONG message = 0, id = 0; if (window && signame && sigfunc) @@ -12412,7 +12915,7 @@ char buffer[16]; HWND owner; - _snprintf(buffer, 15, "_dw_id%d", (int)window); + _snprintf(buffer, 15, "_dw_id%d", (int)(intptr_t)window); owner = (HWND)dw_window_get_data(DW_HWND_OBJECT, buffer); /* Make sure there are no dupes from popups */ @@ -12420,11 +12923,11 @@ if (owner) { - id = (ULONG)window; + id = (ULONG)(uintptr_t)window; window = owner; } } - _new_signal(message, window, id, sigfunc, data); + _new_signal(message, window, id, sigfunc, discfunc, data); } } } @@ -12444,9 +12947,16 @@ while(tmp) { - if(((window < (HWND)65536 && (int)window == tmp->id) || tmp->window == window) && tmp->message == message) - { - if(prev) + if(((window < (HWND)65536 && (int)(intptr_t)window == tmp->id) || tmp->window == window) && tmp->message == message) + { + void (DWSIGNAL *discfunc)(HWND, void *) = (void (*)(HWND, void *))tmp->discfunction; + + if(discfunc) + { + discfunc(tmp->window, tmp->data); + } + + if(prev) { prev->next = tmp->next; free(tmp); @@ -12478,8 +12988,15 @@ while(tmp) { - if((window < (HWND)65536 && (int)window == tmp->id) || tmp->window == window) - { + if((window < (HWND)65536 && (int)(intptr_t)window == tmp->id) || tmp->window == window) + { + void (DWSIGNAL *discfunc)(HWND, void *) = (void (*)(HWND, void *))tmp->discfunction; + + if(discfunc) + { + discfunc(tmp->window, tmp->data); + } + if(prev) { prev->next = tmp->next; @@ -12513,8 +13030,15 @@ while(tmp) { - if(((window < (HWND)65536 && (int)window == tmp->id) || tmp->window == window) && tmp->data == data) - { + if(((window < (HWND)65536 && (int)(intptr_t)window == tmp->id) || tmp->window == window) && tmp->data == data) + { + void (DWSIGNAL *discfunc)(HWND, void *) = (void (*)(HWND, void *))tmp->discfunction; + + if(discfunc) + { + discfunc(tmp->window, tmp->data); + } + if(prev) { prev->next = tmp->next; @@ -12569,4 +13093,3 @@ return NULL; #endif } -