Mercurial > install
changeset 2:f3314e97472f
First step in modernizing the installer/2 codebase. Sync up with Dynamic Windows 2.2... only worrying about OS/2 for now.
author | Brian Smith <brian@dbsoft.org> |
---|---|
date | Sun, 13 Nov 2011 07:22:43 -0600 |
parents | 821abb186ec1 |
children | 445f5fc8d53d |
files | configure dw.h install.c instsup.c os2/dw.c packinst/packinst.c rexx.c scripts/finished.cmd scripts/page1.cmd scripts/page2.cmd scripts/page3.cmd scripts/page4.cmd win/dw.c |
diffstat | 7 files changed, 23948 insertions(+), 18472 deletions(-) [+] |
line wrap: on
line diff
--- a/dw.h Fri Feb 18 09:04:25 2011 -0600 +++ b/dw.h Sun Nov 13 07:22:43 2011 -0600 @@ -1,1085 +1,1719 @@ -/* $Id: dw.h,v 1.33 2003/12/02 18:40:52 bsmith Exp $ */ - -#ifndef _H_DW -#define _H_DW - -/* Dynamic Windows version numbers */ -#define DW_MAJOR_VERSION 1 -#define DW_MINOR_VERSION 0 -#define DW_SUB_VERSION 0 - -/* These corespond to the entries in the color - * arrays in the Win32 dw.c, they are also the - * same as DOS ANSI colors. - */ -#define DW_CLR_BLACK 0 -#define DW_CLR_DARKRED 1 -#define DW_CLR_DARKGREEN 2 -#define DW_CLR_BROWN 3 -#define DW_CLR_DARKBLUE 4 -#define DW_CLR_DARKPINK 5 -#define DW_CLR_DARKCYAN 6 -#define DW_CLR_PALEGRAY 7 -#define DW_CLR_DARKGRAY 8 -#define DW_CLR_RED 9 -#define DW_CLR_GREEN 10 -#define DW_CLR_YELLOW 11 -#define DW_CLR_BLUE 12 -#define DW_CLR_PINK 13 -#define DW_CLR_CYAN 14 -#define DW_CLR_WHITE 15 -#define DW_CLR_DEFAULT 16 - -/* Signal handler defines */ -#define DW_SIGNAL_CONFIGURE "configure_event" -#define DW_SIGNAL_KEY_PRESS "key_press_event" -#define DW_SIGNAL_BUTTON_PRESS "button_press_event" -#define DW_SIGNAL_BUTTON_RELEASE "button_release_event" -#define DW_SIGNAL_MOTION_NOTIFY "motion_notify_event" -#define DW_SIGNAL_DELETE "delete_event" -#define DW_SIGNAL_EXPOSE "expose_event" -#define DW_SIGNAL_CLICKED "clicked" -#define DW_SIGNAL_ITEM_ENTER "container-select" -#define DW_SIGNAL_ITEM_CONTEXT "container-context" -#define DW_SIGNAL_ITEM_SELECT "tree-select" -#define DW_SIGNAL_LIST_SELECT "item-select" -#define DW_SIGNAL_SET_FOCUS "set-focus" -#define DW_SIGNAL_VALUE_CHANGED "value_changed" -#define DW_SIGNAL_SWITCH_PAGE "switch-page" -#define DW_SIGNAL_COLUMN_CLICK "click-column" -#define DW_SIGNAL_TREE_EXPAND "tree-expand" - -#if defined(__OS2__) || defined(__WIN32__) || defined(__MAC__) || defined(WINNT) || defined(__EMX__) -/* OS/2, Windows or MacOS */ - -#if defined(__IBMC__) && !defined(API) -#define API _System -#endif - -/* Used internally */ -#define TYPEBOX 0 -#define TYPEITEM 1 - -#define SIZESTATIC 0 -#define SIZEEXPAND 1 - -#define SPLITBAR_WIDTH 4 -#define BUBBLE_HELP_MAX 256 - -typedef struct _user_data -{ - struct _user_data *next; - void *data; - char *varname; -} UserData; - -/* OS/2 Specific section */ -#if defined(__OS2__) || defined(__EMX__) -#define INCL_DOS -#define INCL_WIN -#define INCL_GPI - -#include <os2.h> - -#define DW_DT_LEFT DT_LEFT -#define DW_DT_QUERYEXTENT DT_QUERYEXTENT -#define DW_DT_UNDERSCORE DT_UNDERSCORE -#define DW_DT_STRIKEOUT DT_STRIKEOUT -#define DW_DT_TEXTATTRS DT_TEXTATTRS -#define DW_DT_EXTERNALLEADING DT_EXTERNALLEADING -#define DW_DT_CENTER DT_CENTER -#define DW_DT_RIGHT DT_RIGHT -#define DW_DT_TOP DT_TOP -#define DW_DT_VCENTER DT_VCENTER -#define DW_DT_BOTTOM DT_BOTTOM -#define DW_DT_HALFTONE DT_HALFTONE -#define DW_DT_MNEMONIC DT_MNEMONIC -#define DW_DT_WORDBREAK DT_WORDBREAK -#define DW_DT_ERASERECT DT_ERASERECT - -#ifndef FCF_CLOSEBUTTON -#define FCF_CLOSEBUTTON 0x04000000L -#endif - -#define DW_FCF_TITLEBAR FCF_TITLEBAR -#define DW_FCF_SYSMENU (FCF_SYSMENU | FCF_CLOSEBUTTON) -#define DW_FCF_MENU FCF_MENU -#define DW_FCF_SIZEBORDER FCF_SIZEBORDER -#define DW_FCF_MINBUTTON FCF_MINBUTTON -#define DW_FCF_MAXBUTTON FCF_MAXBUTTON -#define DW_FCF_MINMAX FCF_MINMAX -#define DW_FCF_VERTSCROLL FCF_VERTSCROLL -#define DW_FCF_HORZSCROLL FCF_HORZSCROLL -#define DW_FCF_DLGBORDER FCF_DLGBORDER -#define DW_FCF_BORDER FCF_BORDER -#define DW_FCF_SHELLPOSITION FCF_SHELLPOSITION -#define DW_FCF_TASKLIST FCF_TASKLIST -#define DW_FCF_NOBYTEALIGN FCF_NOBYTEALIGN -#define DW_FCF_NOMOVEWITHOWNER FCF_NOMOVEWITHOWNER -#define DW_FCF_SYSMODAL FCF_SYSMODAL -#define DW_FCF_HIDEBUTTON FCF_HIDEBUTTON -#define DW_FCF_HIDEMAX FCF_HIDEMAX -#define DW_FCF_AUTOICON FCF_AUTOICON -#define DW_FCF_MAXIMIZE WS_MAXIMIZED -#define DW_FCF_MINIMIZE WS_MINIMIZED - -#define DW_CFA_BITMAPORICON CFA_BITMAPORICON -#define DW_CFA_STRING CFA_STRING -#define DW_CFA_ULONG CFA_ULONG -#define DW_CFA_TIME CFA_TIME -#define DW_CFA_DATE CFA_DATE -#define DW_CFA_CENTER CFA_CENTER -#define DW_CFA_LEFT CFA_LEFT -#define DW_CFA_RIGHT CFA_RIGHT -#define DW_CFA_HORZSEPARATOR CFA_HORZSEPARATOR -#define DW_CFA_SEPARATOR CFA_SEPARATOR -#define DW_CFA_STRINGANDICON 0 - -#define DW_CRA_SELECTED CRA_SELECTED -#define DW_CRA_CURSORED CRA_CURSORED - -#define DW_LS_MULTIPLESEL LS_MULTIPLESEL - -#define DW_LIT_NONE -1 - -#define DW_MLE_CASESENSITIVE MLFSEARCH_CASESENSITIVE - -#define DW_POINTER_ARROW SPTR_ARROW -#define DW_POINTER_CLOCK SPTR_WAIT - -#define DW_OS2_NEW_WINDOW 1 - -/* flag values for dw_messagebox() */ -#define DW_MB_OK MB_OK -#define DW_MB_OKCANCEL MB_OKCANCEL -#define DW_MB_YESNO MB_YESNO -#define DW_MB_YESNOCANCEL MB_YESNOCANCEL - -#define DW_MB_WARNING MB_WARNING -#define DW_MB_ERROR MB_ERROR -#define DW_MB_INFORMATION MB_INFORMATION -#define DW_MB_QUESTION MB_QUERY - -/* Virtual Key Codes */ -#define VK_LBUTTON VK_BUTTON1 -#define VK_RBUTTON VK_BUTTON2 -#define VK_MBUTTON VK_BUTTON3 -#define VK_RETURN VK_NEWLINE -#define VK_SNAPSHOT VK_PRINTSCRN -#define VK_CANCEL VK_BREAK -#define VK_CAPITAL VK_CAPSLOCK -#define VK_ESCAPE VK_ESC -#define VK_PRIOR VK_PAGEUP -#define VK_NEXT VK_PAGEDOWN -#define VK_SELECT 133 -#define VK_EXECUTE 134 -#define VK_PRINT 135 -#define VK_HELP 136 -#define VK_LWIN 137 -#define VK_RWIN 138 -#define VK_MULTIPLY ('*' + 128) -#define VK_ADD ('+' + 128) -#define VK_SEPARATOR 141 -#define VK_SUBTRACT ('-' + 128) -#define VK_DECIMAL ('.' + 128) -#define VK_DIVIDE ('/' + 128) -#define VK_SCROLL VK_SCRLLOCK -#define VK_LSHIFT VK_SHIFT -#define VK_RSHIFT 147 -#define VK_LCONTROL VK_CTRL -#define VK_RCONTROL 149 -#define VK_NUMPAD0 ('0' + 128) -#define VK_NUMPAD1 ('1' + 128) -#define VK_NUMPAD2 ('2' + 128) -#define VK_NUMPAD3 ('3' + 128) -#define VK_NUMPAD4 ('4' + 128) -#define VK_NUMPAD5 ('5' + 128) -#define VK_NUMPAD6 ('6' + 128) -#define VK_NUMPAD7 ('7' + 128) -#define VK_NUMPAD8 ('8' + 128) -#define VK_NUMPAD9 ('9' + 128) -#define VK_BACK VK_BACKSPACE -#define VK_LMENU VK_MENU -#define VK_RMENU VK_MENU - -typedef struct _window_data { - PFNWP oldproc; - UserData *root; - HWND clickdefault; - ULONG flags; - void *data; -} WindowData; - -typedef struct _hpixmap { - unsigned long width, height; - HDC hdc; - HPS hps; - HBITMAP hbm; - HWND handle; -} *HPIXMAP; - -typedef void *HTREEITEM; -typedef HWND HMENUI; -typedef HMODULE HMOD; -typedef unsigned short UWORD; - -extern HAB dwhab; -extern HMQ dwhmq; -#endif - -#if defined(__MAC__) -/* MacOS specific section */ -#include <Carbon/Carbon.h> - -typedef ControlRef HWND; -typedef ThreadID DWTID; -typedef unsigned long ULONG; -typedef long LONG; -typedef unsigned short USHORT; -typedef short SHORT; -typedef unsigned short UWORD; -typedef short WORD ; -typedef unsigned char UCHAR; -typedef char CHAR; -typedef unsigned UINT; -typedef int INT; -typedef void *HMTX; -typedef void *HEV; -typedef void *HMOD; -typedef void *HPIXMAP; -typedef void *HTREEITEM; -typedef void *HMENUI; - -typedef struct _window_data { - UserData *root; - HWND clickdefault; - ULONG flags; - void *data; -} WindowData; - -#define DW_DT_LEFT 0 -#define DW_DT_QUERYEXTENT 0 -#define DW_DT_UNDERSCORE 0 -#define DW_DT_STRIKEOUT 0 -#define DW_DT_TEXTATTRS 0 -#define DW_DT_EXTERNALLEADING 0 -#define DW_DT_CENTER 0 -#define DW_DT_RIGHT 0 -#define DW_DT_TOP 0 -#define DW_DT_VCENTER 0 -#define DW_DT_BOTTOM 0 -#define DW_DT_HALFTONE 0 -#define DW_DT_MNEMONIC 0 -#define DW_DT_WORDBREAK 0 -#define DW_DT_ERASERECT 0 - -#define DW_FCF_TITLEBAR 0 -#define DW_FCF_SYSMENU 0 -#define DW_FCF_MENU 0 -#define DW_FCF_SIZEBORDER 0 -#define DW_FCF_MINBUTTON 0 -#define DW_FCF_MAXBUTTON 0 -#define DW_FCF_MINMAX 0 -#define DW_FCF_VERTSCROLL 0 -#define DW_FCF_HORZSCROLL 0 -#define DW_FCF_DLGBORDER 0 -#define DW_FCF_BORDER 0 -#define DW_FCF_SHELLPOSITION 0 -#define DW_FCF_TASKLIST 0 -#define DW_FCF_NOBYTEALIGN 0 -#define DW_FCF_NOMOVEWITHOWNER 0 -#define DW_FCF_SYSMODAL 0 -#define DW_FCF_HIDEBUTTON 0 -#define DW_FCF_HIDEMAX 0 -#define DW_FCF_AUTOICON 0 -#define DW_FCF_MAXIMIZE 0 -#define DW_FCF_MINIMIZE 0 - -#define DW_CFA_BITMAPORICON 1 -#define DW_CFA_STRING (1 << 1) -#define DW_CFA_ULONG (1 << 2) -#define DW_CFA_TIME (1 << 3) -#define DW_CFA_DATE (1 << 4) -#define DW_CFA_CENTER (1 << 5) -#define DW_CFA_LEFT (1 << 6) -#define DW_CFA_RIGHT (1 << 7) -#define DW_CFA_STRINGANDICON (1 << 8) -#define DW_CFA_HORZSEPARATOR 0 -#define DW_CFA_SEPARATOR 0 - -#define DW_CRA_SELECTED 1 -#define DW_CRA_CURSORED (1 << 1) - -#define DW_LS_MULTIPLESEL 1 - -#define DW_LIT_NONE -1 - -#define DW_MLE_CASESENSITIVE MLFSEARCH_CASESENSITIVE - -#define DW_POINTER_ARROW 0 -#define DW_POINTER_CLOCK watchCursor - -#define HWND_DESKTOP ((HWND)0) - -/* flag values for dw_messagebox() */ -#define DW_MB_OK (1 << 1) -#define DW_MB_OKCANCEL (1 << 2) -#define DW_MB_YESNO (1 << 3) -#define DW_MB_YESNOCANCEL (1 << 4) - -#define DW_MB_WARNING (1 << 10) -#define DW_MB_ERROR (1 << 11) -#define DW_MB_INFORMATION (1 << 12) -#define DW_MB_QUESTION (1 << 13) - - -#endif - -/* Windows specific section */ -#if defined(__WIN32__) || defined(WINNT) -#include <windows.h> -#include <commctrl.h> - -#if defined(MSVC) && !defined(API) -#define API _cdecl -#endif - -#define DW_DT_LEFT SS_LEFT -#define DW_DT_QUERYEXTENT 0 -#define DW_DT_UNDERSCORE 0 -#define DW_DT_STRIKEOUT 0 -#define DW_DT_TEXTATTRS 0 -#define DW_DT_EXTERNALLEADING 0 -#define DW_DT_CENTER SS_CENTER -#define DW_DT_RIGHT SS_RIGHT -#define DW_DT_TOP 0 -#define DW_DT_VCENTER SS_NOPREFIX -#define DW_DT_BOTTOM 0 -#define DW_DT_HALFTONE 0 -#define DW_DT_MNEMONIC 0 -#define DW_DT_WORDBREAK 0 -#define DW_DT_ERASERECT 0 - -#define DW_FCF_TITLEBAR WS_CAPTION -#define DW_FCF_SYSMENU WS_SYSMENU -#define DW_FCF_MENU 0 -#define DW_FCF_SIZEBORDER WS_THICKFRAME -#define DW_FCF_MINBUTTON WS_MINIMIZEBOX -#define DW_FCF_MAXBUTTON WS_MAXIMIZEBOX -#define DW_FCF_MINMAX (WS_MINIMIZEBOX|WS_MAXIMIZEBOX) -#define DW_FCF_VERTSCROLL WS_VSCROLL -#define DW_FCF_HORZSCROLL WS_HSCROLL -#define DW_FCF_DLGBORDER WS_DLGFRAME -#define DW_FCF_BORDER WS_BORDER -#define DW_FCF_SHELLPOSITION 0 -#define DW_FCF_TASKLIST WS_VSCROLL -#define DW_FCF_NOBYTEALIGN 0 -#define DW_FCF_NOMOVEWITHOWNER 0 -#define DW_FCF_SYSMODAL 0 -#define DW_FCF_HIDEBUTTON WS_MINIMIZEBOX -#define DW_FCF_HIDEMAX 0 -#define DW_FCF_AUTOICON 0 -#define DW_FCF_MAXIMIZE WS_MAXIMIZE -#define DW_FCF_MINIMIZE WS_MINIMIZE - -#define DW_CFA_BITMAPORICON 1 -#define DW_CFA_STRING (1 << 1) -#define DW_CFA_ULONG (1 << 2) -#define DW_CFA_TIME (1 << 3) -#define DW_CFA_DATE (1 << 4) -#define DW_CFA_CENTER (1 << 5) -#define DW_CFA_LEFT (1 << 6) -#define DW_CFA_RIGHT (1 << 7) -#define DW_CFA_STRINGANDICON (1 << 8) -#define DW_CFA_HORZSEPARATOR 0 -#define DW_CFA_SEPARATOR 0 - -#define DW_CRA_SELECTED LVNI_SELECTED -#define DW_CRA_CURSORED LVNI_FOCUSED - -#define DW_LS_MULTIPLESEL LBS_MULTIPLESEL - -#define DW_LIT_NONE -1 - -#define DW_MLE_CASESENSITIVE 1 - -#define DW_POINTER_ARROW 32512 -#define DW_POINTER_CLOCK 32514 - -/* flag values for dw_messagebox() */ -#define DW_MB_OK MB_OK -#define DW_MB_OKCANCEL MB_OKCANCEL -#define DW_MB_YESNO MB_YESNO -#define DW_MB_YESNOCANCEL MB_YESNOCANCEL - -#define DW_MB_WARNING MB_ICONWARNING -#define DW_MB_ERROR MB_ICONERROR -#define DW_MB_INFORMATION MB_ICONINFORMATION -#define DW_MB_QUESTION MB_ICONQUESTION - -/* Key Modifiers */ -#define KC_CTRL (1) -#define KC_SHIFT (1 << 1) -#define KC_ALT (1 << 2) - -#define STATICCLASSNAME "STATIC" -#define COMBOBOXCLASSNAME "COMBOBOX" -#define LISTBOXCLASSNAME "LISTBOX" -#define BUTTONCLASSNAME "BUTTON" -#define POPUPMENUCLASSNAME "POPUPMENU" -#define EDITCLASSNAME "EDIT" -#define FRAMECLASSNAME "FRAME" -#define SCROLLBARCLASSNAME "SCROLLBAR" - -#define ClassName "dynamicwindows" -#define SplitbarClassName "dwsplitbar" -#define ObjectClassName "dwobjectclass" -#define DefaultFont NULL - -typedef struct _color { - int fore; - int back; - HWND combo, buddy; - int user; - int vcenter; - HWND clickdefault; - HBRUSH hbrush; - HFONT hfont; - char fontname[128]; - WNDPROC pOldProc; - UserData *root; -} ColorInfo; - -typedef struct _notebookpage { - ColorInfo cinfo; - TC_ITEM item; - HWND hwnd; - int realid; -} NotebookPage; - -typedef HANDLE HMTX; -typedef HANDLE HEV; -typedef HANDLE HMOD; - -typedef struct _container { - ColorInfo cinfo; - ULONG *flags; - WNDPROC pOldProc; - ULONG columns; -} ContainerInfo; - -typedef struct _hpixmap { - unsigned long width, height; - HBITMAP hbm; - HDC hdc; - HWND handle; - void *bits; -} *HPIXMAP; - -typedef HWND HMENUI; -#endif - -typedef struct _item { - /* Item type - Box or Item */ - int type; - /* Handle to Frame or Window */ - HWND hwnd; - /* Width and Height of static size */ - int width, height, origwidth, origheight; - /* Size Type - Static or Expand */ - int hsize, vsize; - /* Padding */ - int pad; - /* Ratio of current item */ - float xratio, yratio; -} Item; - -typedef struct _box { -#if defined(__WIN32__) || defined(WINNT) - ColorInfo cinfo; -#elif defined(__OS2__) || defined(__EMX__) - PFNWP oldproc; - UserData *root; - HWND hwndtitle; - int titlebar; -#endif - /* Number of items in the box */ - int count; - /* Box type - horizontal or vertical */ - int type; - /* Padding */ - int pad, parentpad, grouppadx, grouppady; - /* Groupbox */ - HWND grouphwnd; - /* Default item */ - HWND defaultitem; - /* Used as temporary storage in the calculation stage */ - int upx, upy, minheight, minwidth; - /* Ratio in this box */ - float xratio, yratio, parentxratio, parentyratio; - /* Used for calculating individual item ratios */ - int width, height; - /* Any combinations of flags describing the box */ - unsigned long flags; - /* Array of item structures */ - struct _item *items; -} Box; - -typedef struct _bubblebutton { -#if defined(__WIN32__) || defined(WINNT) - ColorInfo cinfo; - int checkbox; - WNDPROC pOldProc; -#endif -#if defined(__OS2__) || defined(__EMX__) - PFNWP pOldProc; - UserData *root; -#endif - unsigned long id; - char bubbletext[BUBBLE_HELP_MAX]; -} BubbleButton; - -#else -/* GTK Specific section */ -#include <gtk/gtk.h> -#include <gdk/gdkx.h> -#include <gdk/gdkprivate.h> -#include <gdk/gdkkeysyms.h> -#include <pthread.h> -#include <dlfcn.h> - -#define DW_DT_LEFT 1 -#define DW_DT_UNDERSCORE (1 << 1) -#define DW_DT_STRIKEOUT (1 << 2) -#define DW_DT_CENTER (1 << 3) -#define DW_DT_RIGHT (1 << 4) -#define DW_DT_TOP (1 << 5) -#define DW_DT_VCENTER (1 << 6) -#define DW_DT_BOTTOM (1 << 7) -#define DW_DT_HALFTONE (1 << 8) -#define DW_DT_MNEMONIC (1 << 9) -#define DW_DT_WORDBREAK (1 << 10) -#define DW_DT_ERASERECT (1 << 11) - -/* these don't exist under gtk, so make them dummy entries */ -#define DW_DT_QUERYEXTENT 0 -#define DW_DT_TEXTATTRS 0 -#define DW_DT_EXTERNALLEADING 0 - -#define DW_FCF_TITLEBAR 1 -#define DW_FCF_SYSMENU (1 << 1) -#define DW_FCF_MENU (1 << 2) -#define DW_FCF_SIZEBORDER (1 << 3) -#define DW_FCF_MINBUTTON (1 << 4) -#define DW_FCF_MAXBUTTON (1 << 5) -#define DW_FCF_MINMAX (1 << 6) -#define DW_FCF_VERTSCROLL (1 << 7) -#define DW_FCF_HORZSCROLL (1 << 8) -#define DW_FCF_DLGBORDER (1 << 9) -#define DW_FCF_BORDER (1 << 10) -#define DW_FCF_SHELLPOSITION (1 << 11) -#define DW_FCF_TASKLIST (1 << 12) -#define DW_FCF_NOBYTEALIGN (1 << 13) -#define DW_FCF_NOMOVEWITHOWNER (1 << 14) -#define DW_FCF_SYSMODAL (1 << 15) -#define DW_FCF_HIDEBUTTON (1 << 16) -#define DW_FCF_HIDEMAX (1 << 17) -#define DW_FCF_AUTOICON (1 << 18) -#define DW_FCF_MAXIMIZE (1 << 19) -#define DW_FCF_MINIMIZE (1 << 20) - -#define DW_CFA_BITMAPORICON 1 -#define DW_CFA_STRING (1 << 1) -#define DW_CFA_ULONG (1 << 2) -#define DW_CFA_TIME (1 << 3) -#define DW_CFA_DATE (1 << 4) -#define DW_CFA_CENTER (1 << 5) -#define DW_CFA_LEFT (1 << 6) -#define DW_CFA_RIGHT (1 << 7) -#define DW_CFA_HORZSEPARATOR (1 << 8) -#define DW_CFA_SEPARATOR (1 << 9) -#define DW_CFA_STRINGANDICON (1 << 10) - -#define DW_CRA_SELECTED 1 -#define DW_CRA_CURSORED (1 << 1) - -#define DW_LS_MULTIPLESEL 1 - -#define DW_LIT_NONE -1 - -#define DW_MLE_CASESENSITIVE 1 - -#define DW_POINTER_ARROW GDK_TOP_LEFT_ARROW -#define DW_POINTER_CLOCK GDK_WATCH - -#define HWND_DESKTOP ((HWND)0) - -/* flag values for dw_messagebox() */ -#define DW_MB_OK (1 << 1) -#define DW_MB_OKCANCEL (1 << 2) -#define DW_MB_YESNO (1 << 3) -#define DW_MB_YESNOCANCEL (1 << 4) - -#define DW_MB_WARNING (1 << 10) -#define DW_MB_ERROR (1 << 11) -#define DW_MB_INFORMATION (1 << 12) -#define DW_MB_QUESTION (1 << 13) - -/* Virtual Key Codes */ -#define VK_LBUTTON GDK_Pointer_Button1 -#define VK_RBUTTON GDK_Pointer_Button3 -#define VK_CANCEL GDK_Cancel -#define VK_MBUTTON GDK_Pointer_Button2 -#define VK_BACK GDK_BackSpace -#define VK_TAB GDK_Tab -#define VK_CLEAR GDK_Clear -#define VK_RETURN GDK_Return -#define VK_MENU GDK_Menu -#define VK_PAUSE GDK_Pause -#define VK_CAPITAL GDK_Caps_Lock -#define VK_ESCAPE GDK_Escape -#define VK_SPACE GDK_space -#define VK_PRIOR GDK_Page_Up -#define VK_NEXT GDK_Page_Down -#define VK_END GDK_End -#define VK_HOME GDK_Home -#define VK_LEFT GDK_Left -#define VK_UP GDK_Up -#define VK_RIGHT GDK_Right -#define VK_DOWN GDK_Down -#define VK_SELECT GDK_Select -#define VK_PRINT GDK_Sys_Req -#define VK_EXECUTE GDK_Execute -#define VK_SNAPSHOT GDK_Print -#define VK_INSERT GDK_Insert -#define VK_DELETE GDK_Delete -#define VK_HELP GDK_Help -#define VK_LWIN GDK_Super_L -#define VK_RWIN GDK_Super_R -#define VK_NUMPAD0 GDK_KP_0 -#define VK_NUMPAD1 GDK_KP_1 -#define VK_NUMPAD2 GDK_KP_2 -#define VK_NUMPAD3 GDK_KP_3 -#define VK_NUMPAD4 GDK_KP_4 -#define VK_NUMPAD5 GDK_KP_5 -#define VK_NUMPAD6 GDK_KP_6 -#define VK_NUMPAD7 GDK_KP_7 -#define VK_NUMPAD8 GDK_KP_8 -#define VK_NUMPAD9 GDK_KP_9 -#define VK_MULTIPLY GDK_KP_Multiply -#define VK_ADD GDK_KP_Add -#define VK_SEPARATOR GDK_KP_Separator -#define VK_SUBTRACT GDK_KP_Subtract -#define VK_DECIMAL GDK_KP_Decimal -#define VK_DIVIDE GDK_KP_Divide -#define VK_F1 GDK_F1 -#define VK_F2 GDK_F2 -#define VK_F3 GDK_F3 -#define VK_F4 GDK_F4 -#define VK_F5 GDK_F5 -#define VK_F6 GDK_F6 -#define VK_F7 GDK_F7 -#define VK_F8 GDK_F8 -#define VK_F9 GDK_F9 -#define VK_F10 GDK_F10 -#define VK_F11 GDK_F11 -#define VK_F12 GDK_F12 -#define VK_F13 GDK_F13 -#define VK_F14 GDK_F14 -#define VK_F15 GDK_F15 -#define VK_F16 GDK_F16 -#define VK_F17 GDK_F17 -#define VK_F18 GDK_F18 -#define VK_F19 GDK_F19 -#define VK_F20 GDK_F20 -#define VK_F21 GDK_F21 -#define VK_F22 GDK_F22 -#define VK_F23 GDK_F23 -#define VK_F24 GDK_F24 -#define VK_NUMLOCK GDK_Num_Lock -#define VK_SCROLL GDK_Scroll_Lock -#define VK_LSHIFT GDK_Shift_L -#define VK_RSHIFT GDK_Shift_R -#define VK_LCONTROL GDK_Control_L -#define VK_RCONTROL GDK_Control_R -#define VK_LMENU GDK_Menu -#define VK_RMENU GDK_Menu - -/* Key Modifiers */ -#define KC_CTRL GDK_CONTROL_MASK -#define KC_SHIFT GDK_SHIFT_MASK -#define KC_ALT GDK_MOD1_MASK - -typedef GtkWidget *HWND; -#ifndef _ENVRNMNT_H -typedef unsigned long ULONG; -#endif -typedef long LONG; -typedef unsigned short USHORT; -typedef short SHORT; -typedef unsigned short UWORD; -typedef short WORD ; -typedef unsigned char UCHAR; -typedef char CHAR; -typedef unsigned UINT; -typedef int INT; -typedef pthread_mutex_t *HMTX; -typedef struct _dw_unix_event { - pthread_mutex_t mutex; - pthread_cond_t event; - pthread_t thread; - int alive; - int posted; -} *HEV; -typedef pthread_t DWTID; -typedef void * HMOD; - -typedef struct _hpixmap { - unsigned long width, height; - GdkPixmap *pixmap; - HWND handle; -} *HPIXMAP; - -typedef GtkWidget *HMENUI; -typedef void *HTREEITEM; - -typedef struct _resource_struct { - long resource_max, *resource_id; - char **resource_data; -} DWResources; - -#if !defined(DW_RESOURCES) || defined(BUILD_DLL) -static DWResources _resources = { 0, 0, 0 }; -#else -extern DWResources _resources; -#endif - -#endif - -#if !defined(__OS2__) && !defined(__EMX__) -typedef struct _CDATE -{ - UCHAR day; - UCHAR month; - USHORT year; -} CDATE; -typedef CDATE *PCDATE; - -typedef struct _CTIME -{ - UCHAR hours; - UCHAR minutes; - UCHAR seconds; - UCHAR ucReserved; -} CTIME; -typedef CTIME *PCTIME; -#endif - -#if defined(__OS2__) || defined(__WIN32__) || defined(WINNT) || defined(__EMX__) -typedef unsigned long DWTID; -#endif - -typedef struct _dwenv { - /* Operating System Name and DW Build Date/Time */ - char osName[30], buildDate[30], buildTime[30]; - /* Versions and builds */ - short MajorVersion, MinorVersion, MajorBuild, MinorBuild; - /* Dynamic Window version */ - short DWMajorVersion, DWMinorVersion, DWSubVersion; -} DWEnv; - - -typedef struct _dwexpose { - int x, y; - int width, height; -} DWExpose; - -typedef struct _dwdialog { - HEV eve; - int done; - int method; - void *data, *result; -} DWDialog; - -#define DW_SIGNAL_FUNC(a) ((void *)a) - -#define DW_DESKTOP HWND_DESKTOP -#define DW_MINIMIZED 1 - -#define DW_BUTTON1_MASK 1 -#define DW_BUTTON2_MASK (1 << 1) -#define DW_BUTTON3_MASK (1 << 2) - -#define DW_EXEC_CON 0 -#define DW_EXEC_GUI 1 - -#define DW_FILE_OPEN 0 -#define DW_FILE_SAVE 1 -#define DW_DIRECTORY_OPEN 2 - -#define DW_HORZ 0 -#define DW_VERT 1 - -/* Obsolete, should disappear sometime */ -#define BOXHORZ DW_HORZ -#define BOXVERT DW_VERT - -#define DW_SCROLL_UP 0 -#define DW_SCROLL_DOWN 1 -#define DW_SCROLL_TOP 2 -#define DW_SCROLL_BOTTOM 3 - -/* return values for dw_messagebox() */ -#define DW_MB_RETURN_OK 0 -#define DW_MB_RETURN_YES 1 -#define DW_MB_RETURN_NO 0 -#define DW_MB_RETURN_CANCEL 2 - -#define DW_PIXMAP_WIDTH(x) (x ? x->width : 0) -#define DW_PIXMAP_HEIGHT(x) (x ? x->height : 0) - -#define DW_RGB_COLOR (0xF0000000) -#define DW_RGB_TRANSPARENT (0x0F000000) -#define DW_RGB_MASK (0x00FFFFFF) -#define DW_RED_MASK (0x000000FF) -#define DW_GREEN_MASK (0x0000FF00) -#define DW_BLUE_MASK (0x00FF0000) -#define DW_RED_VALUE(a) (a & DW_RED_MASK) -#define DW_GREEN_VALUE(a) ((a & DW_GREEN_MASK) >> 8) -#define DW_BLUE_VALUE(a) ((a & DW_BLUE_MASK) >> 16) -#define DW_RGB(a, b, c) (0xF0000000 | a | b << 8 | c << 16) - -#define DW_MENU_SEPARATOR "" -#define DW_NOMENU 0 - -#if defined(__OS2__) || defined(__EMX__) -#define DW_OS2_RGB(a) ((DW_RED_VALUE(a) << 16) | (DW_GREEN_VALUE(a) << 8) | DW_BLUE_VALUE(a)) -#endif - -#ifndef API -#define API -#endif - -#define DWSIGNAL API - -/* Let other APIs know what types we've defined, - * Regina REXX in particular, on Unix. - */ -#define ULONG_TYPEDEFED 1 -#define LONG_TYPEDEFED 1 -#define USHORT_TYPEDEFED 1 -#define SHORT_TYPEDEFED 1 -#define UWORD_TYPEDEFED 1 -#define WORD_TYPEDEFED 1 -#define UCHAR_TYPEDEFED 1 -#define CHAR_TYPEDEFED 1 -#define UINT_TYPEDEFED 1 -#define INT_TYPEDEFED 1 - -/* Public function prototypes */ -void API dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad); -void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad); -#if !defined(__OS2__) && !defined(__WIN32__) && !defined(__EMX__) && !defined(__MAC__) -int API dw_int_init(DWResources *res, int newthread, int *argc, char **argv[]); -#define dw_init(a, b, c) dw_int_init(&_resources, a, &b, &c) -#else -int API dw_init(int newthread, int argc, char *argv[]); -#endif -void API dw_main(void); -void API dw_main_sleep(int seconds); -void API dw_main_iteration(void); -void API dw_free(void *ptr); -int API dw_window_show(HWND handle); -int API dw_window_hide(HWND handle); -int API dw_window_minimize(HWND handle); -int API dw_window_raise(HWND handle); -int API dw_window_lower(HWND handle); -int API dw_window_destroy(HWND handle); -void API dw_window_redraw(HWND handle); -int API dw_window_set_font(HWND handle, char *fontname); -int API dw_window_set_color(HWND handle, unsigned long fore, unsigned long back); -HWND API dw_window_new(HWND hwndOwner, char *title, unsigned long flStyle); -HWND API dw_box_new(int type, int pad); -HWND API dw_groupbox_new(int type, int pad, char *title); -HWND API dw_mdi_new(unsigned long id); -HWND API dw_bitmap_new(unsigned long id); -HWND API dw_bitmapbutton_new(char *text, unsigned long id); -HWND API dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename); -HWND API dw_container_new(unsigned long id, int multi); -HWND API dw_tree_new(unsigned long id); -HWND API dw_text_new(char *text, unsigned long id); -HWND API dw_status_text_new(char *text, unsigned long id); -HWND API dw_mle_new(unsigned long id); -HWND API dw_entryfield_new(char *text, unsigned long id); -HWND API dw_entryfield_password_new(char *text, ULONG id); -HWND API dw_combobox_new(char *text, unsigned long id); -HWND API dw_button_new(char *text, unsigned long id); -HWND API dw_spinbutton_new(char *text, unsigned long id); -HWND API dw_radiobutton_new(char *text, ULONG id); -HWND API dw_percent_new(unsigned long id); -HWND API dw_slider_new(int vertical, int increments, ULONG id); -HWND API dw_scrollbar_new(int vertical, int increments, ULONG id); -HWND API dw_checkbox_new(char *text, unsigned long id); -HWND API dw_listbox_new(unsigned long id, int multi); -void API dw_listbox_append(HWND handle, char *text); -void API dw_listbox_clear(HWND handle); -int API dw_listbox_count(HWND handle); -void API dw_listbox_set_top(HWND handle, int top); -void API dw_listbox_select(HWND handle, int index, int state); -void API dw_listbox_delete(HWND handle, int index); -void API dw_listbox_query_text(HWND handle, unsigned int index, char *buffer, unsigned int length); -void API dw_listbox_set_text(HWND handle, unsigned int index, char *buffer); -unsigned int API dw_listbox_selected(HWND handle); -int API dw_listbox_selected_multi(HWND handle, int where); -unsigned int API dw_percent_query_range(HWND handle); -void API dw_percent_set_pos(HWND handle, unsigned int position); -unsigned int API dw_slider_query_pos(HWND handle); -void API dw_slider_set_pos(HWND handle, unsigned int position); -unsigned int API dw_scrollbar_query_pos(HWND handle); -void API dw_scrollbar_set_pos(HWND handle, unsigned int position); -void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible); -void API dw_window_set_pos(HWND handle, unsigned long x, unsigned long y); -void API dw_window_set_usize(HWND handle, unsigned long width, unsigned long height); -void API dw_window_set_pos_size(HWND handle, unsigned long x, unsigned long y, unsigned long width, unsigned long height); -void API dw_window_get_pos_size(HWND handle, unsigned long *x, unsigned long *y, unsigned long *width, unsigned long *height); -void API dw_window_set_style(HWND handle, unsigned long style, unsigned long mask); -void API dw_window_set_icon(HWND handle, unsigned long id); -void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename); -char * API dw_window_get_text(HWND handle); -void API dw_window_set_text(HWND handle, char *text); -int API dw_window_set_border(HWND handle, int border); -void API dw_window_disable(HWND handle); -void API dw_window_enable(HWND handle); -void API dw_window_capture(HWND handle); -void API dw_window_release(void); -void API dw_window_reparent(HWND handle, HWND newparent); -void API dw_window_pointer(HWND handle, int pointertype); -void API dw_window_default(HWND window, HWND defaultitem); -void API dw_window_click_default(HWND window, HWND next); -unsigned int API dw_mle_import(HWND handle, char *buffer, int startpoint); -void API dw_mle_export(HWND handle, char *buffer, int startpoint, int length); -void API dw_mle_query(HWND handle, unsigned long *bytes, unsigned long *lines); -void API dw_mle_delete(HWND handle, int startpoint, int length); -void API dw_mle_clear(HWND handle); -void API dw_mle_freeze(HWND handle); -void API dw_mle_thaw(HWND handle); -void API dw_mle_set(HWND handle, int point); -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); -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); -void API dw_entryfield_set_limit(HWND handle, ULONG limit); -long API dw_spinbutton_query(HWND handle); -int API dw_checkbox_query(HWND handle); -void API dw_checkbox_set(HWND handle, int value); -HTREEITEM API dw_tree_insert(HWND handle, char *title, unsigned long icon, HTREEITEM parent, void *itemdata); -HTREEITEM API dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, unsigned long icon, HTREEITEM parent, void *itemdata); -void API dw_tree_clear(HWND handle); -void API dw_tree_delete(HWND handle, HTREEITEM item); -void API dw_tree_set(HWND handle, HTREEITEM item, char *title, unsigned long icon); -void API dw_tree_expand(HWND handle, HTREEITEM item); -void API dw_tree_collapse(HWND handle, HTREEITEM item); -void API dw_tree_item_select(HWND handle, HTREEITEM item); -void API dw_tree_set_data(HWND handle, HTREEITEM item, void *itemdata); -void * API dw_tree_get_data(HWND handle, HTREEITEM item); -char * API dw_tree_get_title(HWND handle, HTREEITEM item); -HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item); -int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator); -unsigned long API dw_icon_load(unsigned long module, unsigned long id); -unsigned long API dw_icon_load_from_file(char *filename); -void API dw_icon_free(unsigned long handle); -void * API dw_container_alloc(HWND handle, int rowcount); -void API dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data); -void API dw_container_change_item(HWND handle, int column, int row, void *data); -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_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); -char * API dw_container_query_start(HWND handle, unsigned long flags); -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_delete_row(HWND handle, char *text); -void API dw_container_optimize(HWND handle); -int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count); -void API dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data); -void API dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, unsigned long icon); -void dw_taskbar_insert(HWND handle, unsigned long icon, char *bubbletext); -void dw_taskbar_delete(HWND handle, unsigned long icon); -int API dw_screen_width(void); -int API dw_screen_height(void); -unsigned long API dw_color_depth(void); -HWND API dw_notebook_new(unsigned long id, int top); -unsigned long API dw_notebook_page_new(HWND handle, unsigned long flags, int front); -void API dw_notebook_page_destroy(HWND handle, unsigned int pageid); -void API dw_notebook_page_set_text(HWND handle, unsigned long pageid, char *text); -void API dw_notebook_page_set_status_text(HWND handle, unsigned long pageid, char *text); -void API dw_notebook_page_set(HWND handle, unsigned int pageid); -unsigned long API dw_notebook_page_query(HWND handle); -void API dw_notebook_pack(HWND handle, unsigned long pageid, HWND page); -HWND API dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id); -void API dw_splitbar_set(HWND handle, float percent); -float API dw_splitbar_get(HWND handle); -HMENUI API dw_menu_new(unsigned long id); -HMENUI API dw_menubar_new(HWND location); -HWND API dw_menu_append_item(HMENUI menu, char *title, unsigned long id, unsigned long flags, int end, int check, HMENUI submenu); -void API dw_menu_item_set_check(HMENUI menu, unsigned long id, int check); -void API dw_menu_popup(HMENUI *menu, HWND parent, int x, int y); -void API dw_menu_destroy(HMENUI *menu); -void API dw_pointer_query_pos(long *x, long *y); -void API dw_pointer_set_pos(long x, long y); -void API dw_window_function(HWND handle, void *function, void *data); -HWND API dw_window_from_id(HWND handle, int id); -HMTX API dw_mutex_new(void); -void API dw_mutex_close(HMTX mutex); -void API dw_mutex_lock(HMTX mutex); -void API dw_mutex_unlock(HMTX mutex); -HEV API dw_event_new(void); -int API dw_event_reset(HEV eve); -int API dw_event_post(HEV eve); -int API dw_event_wait(HEV eve, unsigned long timeout); -int API dw_event_close (HEV *eve); -DWTID API dw_thread_new(void *func, void *data, int stack); -void API dw_thread_end(void); -DWTID API dw_thread_id(void); -void API dw_exit(int exitcode); -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); -void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y); -void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2); -void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height); -void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text); -void API dw_font_text_extents(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height); -void API dw_flush(void); -void API dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc); -HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth); -HPIXMAP API dw_pixmap_new_from_file(HWND handle, char *filename); -HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id); -void API dw_pixmap_destroy(HPIXMAP pixmap); -void API dw_beep(int freq, int dur); -int API dw_messagebox(char *title, int flags, char *format, ...); -void API dw_environment_query(DWEnv *env); -int API dw_exec(char *program, int type, char **params); -int API dw_browse(char *url); -char * API dw_file_browse(char *title, char *defpath, char *ext, int flags); -char * API dw_user_dir(void); -DWDialog * API dw_dialog_new(void *data); -int API dw_dialog_dismiss(DWDialog *dialog, void *result); -void * API dw_dialog_wait(DWDialog *dialog); -void API dw_window_set_data(HWND window, char *dataname, void *data); -void * API dw_window_get_data(HWND window, char *dataname); -int API dw_module_load(char *name, HMOD *handle); -int API dw_module_symbol(HMOD handle, char *name, void**func); -int API dw_module_close(HMOD handle); -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_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); - -#endif +/* $Id: dw.h 1311 2011-11-03 23:34:10Z bsmith $ */ + +#ifndef _H_DW +#define _H_DW + +/* Dynamic Windows version numbers */ +#define DW_MAJOR_VERSION 2 +#define DW_MINOR_VERSION 1 +#define DW_SUB_VERSION 0 + +#if !defined(__PHOTON__) +/* These corespond to the entries in the color + * arrays in the Win32 dw.c, they are also the + * same as DOS ANSI colors. + */ +#define DW_CLR_BLACK 0 +#define DW_CLR_DARKRED 1 +#define DW_CLR_DARKGREEN 2 +#define DW_CLR_BROWN 3 +#define DW_CLR_DARKBLUE 4 +#define DW_CLR_DARKPINK 5 +#define DW_CLR_DARKCYAN 6 +#define DW_CLR_PALEGRAY 7 +#define DW_CLR_DARKGRAY 8 +#define DW_CLR_RED 9 +#define DW_CLR_GREEN 10 +#define DW_CLR_YELLOW 11 +#define DW_CLR_BLUE 12 +#define DW_CLR_PINK 13 +#define DW_CLR_CYAN 14 +#define DW_CLR_WHITE 15 +#define DW_CLR_DEFAULT 16 +#endif + +/* Signal handler defines */ +#define DW_SIGNAL_CONFIGURE "configure_event" +#define DW_SIGNAL_KEY_PRESS "key_press_event" +#define DW_SIGNAL_BUTTON_PRESS "button_press_event" +#define DW_SIGNAL_BUTTON_RELEASE "button_release_event" +#define DW_SIGNAL_MOTION_NOTIFY "motion_notify_event" +#define DW_SIGNAL_DELETE "delete_event" +#define DW_SIGNAL_EXPOSE "expose_event" +#define DW_SIGNAL_CLICKED "clicked" +#define DW_SIGNAL_ITEM_ENTER "container-select" +#define DW_SIGNAL_ITEM_CONTEXT "container-context" +#define DW_SIGNAL_ITEM_SELECT "tree-select" +#define DW_SIGNAL_LIST_SELECT "item-select" +#define DW_SIGNAL_SET_FOCUS "set-focus" +#define DW_SIGNAL_VALUE_CHANGED "value_changed" +#define DW_SIGNAL_SWITCH_PAGE "switch-page" +#define DW_SIGNAL_COLUMN_CLICK "click-column" +#define DW_SIGNAL_TREE_EXPAND "tree-expand" + +/* status of menu items */ +#define DW_MIS_ENABLED 1 +#define DW_MIS_DISABLED (1 << 1) +#define DW_MIS_CHECKED (1 << 2) +#define DW_MIS_UNCHECKED (1 << 3) + +/* ensure we can build the Gtk port with MingW on Windows */ +#if defined(DW_USE_GTK) && defined(__MINGW32__) +# ifndef GDK_WINDOWING_WIN32 +# define GDK_WINDOWING_WIN32 +# endif +#endif + +#if defined(__OS2__) || (defined(__WIN32__) && !defined(GDK_WINDOWING_WIN32)) || defined(__MAC__) || (defined(WINNT) && !defined(GDK_WINDOWING_WIN32)) || defined(__EMX__) +/* OS/2, Windows or MacOS */ + +#if (defined(__IBMC__) || defined(_System)) && !defined(API) +#define API _System +#endif + +/* Used internally */ +#define TYPEBOX 0 +#define TYPEITEM 1 + +#define SIZESTATIC 0 +#define SIZEEXPAND 1 + +#define SPLITBAR_WIDTH 4 +#define BUBBLE_HELP_MAX 256 + +typedef struct _user_data +{ + struct _user_data *next; + void *data; + char *varname; +} UserData; + +/* OS/2 Specific section */ +#if defined(__OS2__) || defined(__EMX__) +#define INCL_DOS +#define INCL_WIN +#define INCL_GPI + +#include <os2.h> + +#define DW_DT_LEFT DT_LEFT +#define DW_DT_QUERYEXTENT DT_QUERYEXTENT +#define DW_DT_UNDERSCORE DT_UNDERSCORE +#define DW_DT_STRIKEOUT DT_STRIKEOUT +#define DW_DT_TEXTATTRS DT_TEXTATTRS +#define DW_DT_EXTERNALLEADING DT_EXTERNALLEADING +#define DW_DT_CENTER DT_CENTER +#define DW_DT_RIGHT DT_RIGHT +#define DW_DT_TOP DT_TOP +#define DW_DT_VCENTER DT_VCENTER +#define DW_DT_BOTTOM DT_BOTTOM +#define DW_DT_HALFTONE DT_HALFTONE +#define DW_DT_MNEMONIC DT_MNEMONIC +#define DW_DT_WORDBREAK DT_WORDBREAK +#define DW_DT_ERASERECT DT_ERASERECT + +#ifndef FCF_CLOSEBUTTON +#define FCF_CLOSEBUTTON 0x04000000L +#endif + +#define DW_FCF_CLOSEBUTTON 0 +#define DW_FCF_TITLEBAR FCF_TITLEBAR +#define DW_FCF_SYSMENU (FCF_SYSMENU | FCF_CLOSEBUTTON) +#define DW_FCF_MENU FCF_MENU +#define DW_FCF_SIZEBORDER FCF_SIZEBORDER +#define DW_FCF_MINBUTTON FCF_MINBUTTON +#define DW_FCF_MAXBUTTON FCF_MAXBUTTON +#define DW_FCF_MINMAX FCF_MINMAX +#define DW_FCF_VERTSCROLL FCF_VERTSCROLL +#define DW_FCF_HORZSCROLL FCF_HORZSCROLL +#define DW_FCF_DLGBORDER FCF_DLGBORDER +#define DW_FCF_BORDER FCF_BORDER +#define DW_FCF_SHELLPOSITION FCF_SHELLPOSITION +#define DW_FCF_TASKLIST FCF_TASKLIST +#define DW_FCF_NOBYTEALIGN FCF_NOBYTEALIGN +#define DW_FCF_NOMOVEWITHOWNER FCF_NOMOVEWITHOWNER +#define DW_FCF_SYSMODAL FCF_SYSMODAL +#define DW_FCF_HIDEBUTTON FCF_HIDEBUTTON +#define DW_FCF_HIDEMAX FCF_HIDEMAX +#define DW_FCF_AUTOICON FCF_AUTOICON +#define DW_FCF_MAXIMIZE WS_MAXIMIZED +#define DW_FCF_MINIMIZE WS_MINIMIZED + +#define DW_CFA_BITMAPORICON CFA_BITMAPORICON +#define DW_CFA_STRING CFA_STRING +#define DW_CFA_ULONG CFA_ULONG +#define DW_CFA_TIME CFA_TIME +#define DW_CFA_DATE CFA_DATE +#define DW_CFA_CENTER CFA_CENTER +#define DW_CFA_LEFT CFA_LEFT +#define DW_CFA_RIGHT CFA_RIGHT +#define DW_CFA_HORZSEPARATOR CFA_HORZSEPARATOR +#define DW_CFA_SEPARATOR CFA_SEPARATOR +#define DW_CFA_STRINGANDICON 0 + +#define DW_CRA_SELECTED CRA_SELECTED +#define DW_CRA_CURSORED CRA_CURSORED + +#define DW_LS_MULTIPLESEL LS_MULTIPLESEL + +#define DW_LIT_NONE -1 + +#define DW_MLE_CASESENSITIVE MLFSEARCH_CASESENSITIVE + +#define DW_POINTER_DEFAULT 0 +#define DW_POINTER_ARROW SPTR_ARROW +#define DW_POINTER_CLOCK SPTR_WAIT +#define DW_POINTER_QUESTION SPTR_ICONQUESTION + +#define DW_BS_NOBORDER BS_NOBORDER + +#define DW_OS2_NEW_WINDOW 1 + +/* flag values for dw_messagebox() */ +#define DW_MB_OK MB_OK +#define DW_MB_OKCANCEL MB_OKCANCEL +#define DW_MB_YESNO MB_YESNO +#define DW_MB_YESNOCANCEL MB_YESNOCANCEL + +#define DW_MB_WARNING MB_WARNING +#define DW_MB_ERROR MB_ERROR +#define DW_MB_INFORMATION MB_INFORMATION +#define DW_MB_QUESTION MB_QUERY + +/* Virtual Key Codes */ +#define VK_LBUTTON VK_BUTTON1 +#define VK_RBUTTON VK_BUTTON2 +#define VK_MBUTTON VK_BUTTON3 +#define VK_RETURN VK_NEWLINE +#define VK_SNAPSHOT VK_PRINTSCRN +#define VK_CANCEL VK_BREAK +#define VK_CAPITAL VK_CAPSLOCK +#define VK_ESCAPE VK_ESC +#define VK_PRIOR VK_PAGEUP +#define VK_NEXT VK_PAGEDOWN +#define VK_SELECT 133 +#define VK_EXECUTE 134 +#define VK_PRINT 135 +#define VK_HELP 136 +#define VK_LWIN 137 +#define VK_RWIN 138 +#define VK_MULTIPLY ('*' + 128) +#define VK_ADD ('+' + 128) +#define VK_SEPARATOR 141 +#define VK_SUBTRACT ('-' + 128) +#define VK_DECIMAL ('.' + 128) +#define VK_DIVIDE ('/' + 128) +#define VK_SCROLL VK_SCRLLOCK +#define VK_LSHIFT VK_SHIFT +#define VK_RSHIFT 147 +#define VK_LCONTROL VK_CTRL +#define VK_RCONTROL 149 +#define VK_NUMPAD0 ('0' + 128) +#define VK_NUMPAD1 ('1' + 128) +#define VK_NUMPAD2 ('2' + 128) +#define VK_NUMPAD3 ('3' + 128) +#define VK_NUMPAD4 ('4' + 128) +#define VK_NUMPAD5 ('5' + 128) +#define VK_NUMPAD6 ('6' + 128) +#define VK_NUMPAD7 ('7' + 128) +#define VK_NUMPAD8 ('8' + 128) +#define VK_NUMPAD9 ('9' + 128) +#define VK_BACK VK_BACKSPACE +#define VK_LMENU VK_MENU +#define VK_RMENU VK_MENU + +typedef struct _window_data { + PFNWP oldproc; + UserData *root; + HWND clickdefault; + ULONG flags; + void *data; +} WindowData; + +typedef struct _hpixmap { + unsigned long width, height; + HDC hdc; + HPS hps; + HBITMAP hbm; + HWND handle, font; + unsigned long transcolor; +} *HPIXMAP; + +typedef void *HTREEITEM; +typedef HWND HMENUI; +typedef HMODULE HMOD; +typedef unsigned short UWORD; +typedef unsigned long HSHM; +typedef unsigned long HICN; + +extern HAB dwhab; +extern HMQ dwhmq; +#endif + +#if defined(__MAC__) +/* MacOS specific section */ +#include <pthread.h> +#include <dlfcn.h> + +/* Unfortunately using Cocoa we can't include + * Cocoa.h from C code, so we have to instead + * use opaque types and use the values from + * Cocoa.h in the header here directly without + * using the symbolic names. + */ + +#define TRUE 1 +#define FALSE 0 + +typedef void *HWND; +typedef void *HSHM; +typedef unsigned long ULONG; +typedef long LONG; +typedef unsigned short USHORT; +typedef short SHORT; +typedef unsigned short UWORD; +typedef short WORD ; +typedef unsigned char UCHAR; +typedef char CHAR; +typedef unsigned UINT; +typedef int INT; +typedef pthread_mutex_t *HMTX; +typedef struct _dw_unix_event { + pthread_mutex_t mutex; + pthread_cond_t event; + pthread_t thread; + int alive; + int posted; +} *HEV; +typedef pthread_t DWTID; +typedef void * HMOD; +struct _dw_unix_shm { + int fd; + char *path; + int sid; + int size; +}; +typedef void *HTREEITEM; +typedef void *HMENUI; +typedef void *HICN; + +typedef struct _window_data { + UserData *root; + HWND clickdefault; + ULONG flags; + void *data; +} WindowData; + +typedef struct _hpixmap { + unsigned long width, height; + void *image, *font; + HWND handle; +} *HPIXMAP; + +void _dw_pool_drain(void); + +#define DW_DT_LEFT 0 /* NSLeftTextAlignment */ +#define DW_DT_QUERYEXTENT 0 +#define DW_DT_UNDERSCORE 0 +#define DW_DT_STRIKEOUT 0 +#define DW_DT_TEXTATTRS 0 +#define DW_DT_EXTERNALLEADING 0 +#define DW_DT_CENTER 2 /* NSCenterTextAlignment */ +#define DW_DT_RIGHT 1 /* NSRightTextAlignment */ +#define DW_DT_TOP 0 +#define DW_DT_VCENTER (1 << 10) +#define DW_DT_BOTTOM 0 +#define DW_DT_HALFTONE 0 +#define DW_DT_MNEMONIC 0 +#define DW_DT_WORDBREAK 0 +#define DW_DT_ERASERECT 0 + +#define DW_FCF_CLOSEBUTTON (1 << 1) /* NSClosableWindowMask */ +#define DW_FCF_TITLEBAR (1 << 0) /* NSTitledWindowMask */ +#define DW_FCF_SYSMENU (1 << 1) /* NSClosableWindowMask */ +#define DW_FCF_MENU 0 +#define DW_FCF_SIZEBORDER (1 << 3) /* NSResizableWindowMask */ +#define DW_FCF_MINBUTTON (1 << 2) /* NSMiniaturizableWindowMask */ +#define DW_FCF_MAXBUTTON 0 +#define DW_FCF_MINMAX (1 << 2) /* NSMiniaturizableWindowMask */ +#define DW_FCF_VERTSCROLL 0 +#define DW_FCF_HORZSCROLL 0 +#define DW_FCF_DLGBORDER 0 +#define DW_FCF_BORDER 0 +#define DW_FCF_SHELLPOSITION 0 +#define DW_FCF_TASKLIST 0 +#define DW_FCF_NOBYTEALIGN 0 +#define DW_FCF_NOMOVEWITHOWNER 0 +#define DW_FCF_SYSMODAL 0 +#define DW_FCF_HIDEBUTTON 0 +#define DW_FCF_HIDEMAX 0 +#define DW_FCF_AUTOICON 0 +#define DW_FCF_MAXIMIZE 0 +#define DW_FCF_MINIMIZE 0 + +#define DW_CFA_BITMAPORICON 1 +#define DW_CFA_STRING (1 << 1) +#define DW_CFA_ULONG (1 << 2) +#define DW_CFA_TIME (1 << 3) +#define DW_CFA_DATE (1 << 4) +#define DW_CFA_CENTER (1 << 5) +#define DW_CFA_LEFT (1 << 6) +#define DW_CFA_RIGHT (1 << 7) +#define DW_CFA_STRINGANDICON (1 << 8) +#define DW_CFA_HORZSEPARATOR 0 +#define DW_CFA_SEPARATOR 0 + +#define DW_CRA_SELECTED 1 +#define DW_CRA_CURSORED (1 << 1) + +#define DW_LS_MULTIPLESEL 1 + +#define DW_LIT_NONE -1 + +#define DW_MLE_CASESENSITIVE 2 /* NSLiteralSearch */ + +#define DW_BS_NOBORDER 1 + +#define DW_POINTER_DEFAULT 0 +#define DW_POINTER_ARROW 1 +#define DW_POINTER_CLOCK 2 +#define DW_POINTER_QUESTION 3 + +#define HWND_DESKTOP ((HWND)0) + +/* flag values for dw_messagebox() */ +#define DW_MB_OK (1 << 1) +#define DW_MB_OKCANCEL (1 << 2) +#define DW_MB_YESNO (1 << 3) +#define DW_MB_YESNOCANCEL (1 << 4) + +#define DW_MB_WARNING (1 << 10) +#define DW_MB_ERROR (1 << 11) +#define DW_MB_INFORMATION (1 << 12) +#define DW_MB_QUESTION (1 << 13) + +/* Virtual Key Codes */ +#define VK_LBUTTON 0xFF10 /* TODO */ +#define VK_RBUTTON 0xFF11 /* TODO */ +#define VK_CANCEL 0xFF12 /* TODO */ +#define VK_MBUTTON 0xFF13 /* TODO */ +#define VK_BACK 0x7F +#define VK_TAB 0x09 +#define VK_CLEAR 71 +#define VK_RETURN 13 +#define VK_MENU 0xF735 /* NSMenuFunctionKey */ +#define VK_PAUSE 0xF730 /* NSPauseFunctionKey */ +#define VK_CAPITAL 57 +#define VK_ESCAPE 0x1B +#define VK_SPACE ' ' +#define VK_PRIOR 0xF72C /* NSPageUpFunctionKey */ +#define VK_NEXT 0xF72D /* NSPageDownFunctionKey */ +#define VK_END 0xF72B /* NSEndFunctionKey */ +#define VK_HOME 0xF729 /* NSHomeFunctionKey */ +#define VK_LEFT 0xF702 /* NSLeftArrowFunctionKey */ +#define VK_UP 0xF700 /* NSUpArrowFunctionKey */ +#define VK_RIGHT 0xF703 /* NSRightArrowFunctionKey */ +#define VK_DOWN 0xF701 /* NSDownArrowFunctionKey */ +#define VK_SELECT 0xF741 /* NSSelectFunctionKey */ +#define VK_PRINT 0xF738 /* NSPrintFunctionKey */ +#define VK_EXECUTE 0xF742 /* NSExecuteFunctionKey */ +#define VK_SNAPSHOT 0xF72E /* NSPrintScreenFunctionKey */ +#define VK_INSERT 0xF727 /* NSInsertFunctionKey */ +#define VK_DELETE 0xF728 /* NSDeleteFunctionKey */ +#define VK_HELP 0xF746 /* NSHelpFunctionKey */ +#define VK_LWIN 55 +#define VK_RWIN 0xFF14 /* TODO */ +#define VK_NUMPAD0 82 +#define VK_NUMPAD1 83 +#define VK_NUMPAD2 84 +#define VK_NUMPAD3 85 +#define VK_NUMPAD4 86 +#define VK_NUMPAD5 87 +#define VK_NUMPAD6 88 +#define VK_NUMPAD7 89 +#define VK_NUMPAD8 91 +#define VK_NUMPAD9 92 +#define VK_MULTIPLY 67 +#define VK_ADD 69 +#define VK_SEPARATOR 0xFF15 /* TODO */ +#define VK_SUBTRACT 78 +#define VK_DECIMAL 65 +#define VK_DIVIDE 75 +#define VK_F1 0xF704 /* NSF1FunctionKey */ +#define VK_F2 0xF705 /* NSF2FunctionKey */ +#define VK_F3 0xF706 /* NSF3FunctionKey */ +#define VK_F4 0xF707 /* NSF4FunctionKey */ +#define VK_F5 0xF708 /* NSF5FunctionKey */ +#define VK_F6 0xF709 /* NSF6FunctionKey */ +#define VK_F7 0xF70A /* NSF7FunctionKey */ +#define VK_F8 0xF70B /* NSF8FunctionKey */ +#define VK_F9 0xF70C /* NSF9FunctionKey */ +#define VK_F10 0xF70D /* NSF10FunctionKey */ +#define VK_F11 0xF70E /* NSF11FunctionKey */ +#define VK_F12 0xF70F /* NSF12FunctionKey */ +#define VK_F13 0xF710 /* NSF13FunctionKey */ +#define VK_F14 0xF711 /* NSF14FunctionKey */ +#define VK_F15 0xF712 /* NSF15FunctionKey */ +#define VK_F16 0xF713 /* NSF16FunctionKey */ +#define VK_F17 0xF714 /* NSF17FunctionKey */ +#define VK_F18 0xF715 /* NSF18FunctionKey */ +#define VK_F19 0xF716 /* NSF19FunctionKey */ +#define VK_F20 0xF717 /* NSF20FunctionKey */ +#define VK_F21 0xF718 /* NSF21FunctionKey */ +#define VK_F22 0xF719 /* NSF22FunctionKey */ +#define VK_F23 0xF71A /* NSF23FunctionKey */ +#define VK_F24 0xF71B /* NSF24FunctionKey */ +#define VK_NUMLOCK 0xFF16 /* TODO */ +#define VK_SCROLL 0xF72F /* NSScrollLockFunctionKey */ +#define VK_LSHIFT 56 +#define VK_RSHIFT 60 +#define VK_LCONTROL 59 +#define VK_RCONTROL 62 +#define VK_LMENU 0xF735 /* NSMenuFunctionKey */ +#define VK_RMENU 0xF735 /* NSMenuFunctionKey */ + +/* Key Modifiers */ +#define KC_CTRL (1 << 18) /* NSControlKeyMask */ +#define KC_SHIFT (1 << 17) /* NSShiftKeyMask */ +#define KC_ALT (1 << 19) /* NSAlternateKeyMask */ +#endif + +/* Windows specific section */ +#if defined(__WIN32__) || defined(WINNT) +#include <windows.h> +#include <commctrl.h> + +#if defined(MSVC) && !defined(API) +# ifdef __MINGW32__ +# ifdef BUILD_DLL +# define API APIENTRY __declspec(dllexport) +# else +# define API APIENTRY __declspec(dllimport) +# endif +# else +# define API _cdecl +#endif +#endif + +#define DW_DT_LEFT SS_LEFT +#define DW_DT_QUERYEXTENT 0 +#define DW_DT_UNDERSCORE 0 +#define DW_DT_STRIKEOUT 0 +#define DW_DT_TEXTATTRS 0 +#define DW_DT_EXTERNALLEADING 0 +#define DW_DT_CENTER SS_CENTER +#define DW_DT_RIGHT SS_RIGHT +#define DW_DT_TOP 0 +#define DW_DT_VCENTER SS_NOPREFIX +#define DW_DT_BOTTOM 0 +#define DW_DT_HALFTONE 0 +#define DW_DT_MNEMONIC 0 +#define DW_DT_WORDBREAK 0 +#define DW_DT_ERASERECT 0 + +#define DW_FCF_CLOSEBUTTON 0 +#define DW_FCF_TITLEBAR WS_CAPTION +#define DW_FCF_SYSMENU WS_SYSMENU +#define DW_FCF_MENU 0 +#define DW_FCF_SIZEBORDER WS_THICKFRAME +#define DW_FCF_MINBUTTON WS_MINIMIZEBOX +#define DW_FCF_MAXBUTTON WS_MAXIMIZEBOX +#define DW_FCF_MINMAX (WS_MINIMIZEBOX|WS_MAXIMIZEBOX) +#define DW_FCF_VERTSCROLL WS_VSCROLL +#define DW_FCF_HORZSCROLL WS_HSCROLL +#define DW_FCF_DLGBORDER WS_DLGFRAME +#define DW_FCF_BORDER WS_BORDER +#define DW_FCF_SHELLPOSITION 0 +#define DW_FCF_TASKLIST WS_VSCROLL +#define DW_FCF_NOBYTEALIGN 0 +#define DW_FCF_NOMOVEWITHOWNER 0 +#define DW_FCF_SYSMODAL 0 +#define DW_FCF_HIDEBUTTON WS_MINIMIZEBOX +#define DW_FCF_HIDEMAX (WS_MINIMIZEBOX|WS_MAXIMIZEBOX) +#define DW_FCF_AUTOICON 0 +#define DW_FCF_MAXIMIZE WS_MAXIMIZE +#define DW_FCF_MINIMIZE WS_MINIMIZE + +#define DW_CFA_BITMAPORICON 1 +#define DW_CFA_STRING (1 << 1) +#define DW_CFA_ULONG (1 << 2) +#define DW_CFA_TIME (1 << 3) +#define DW_CFA_DATE (1 << 4) +#define DW_CFA_CENTER (1 << 5) +#define DW_CFA_LEFT (1 << 6) +#define DW_CFA_RIGHT (1 << 7) +#define DW_CFA_STRINGANDICON (1 << 8) +#define DW_CFA_HORZSEPARATOR 0 +#define DW_CFA_SEPARATOR 0 + +#define DW_CRA_SELECTED LVNI_SELECTED +#define DW_CRA_CURSORED LVNI_FOCUSED + +#define DW_LS_MULTIPLESEL LBS_MULTIPLESEL + +#define DW_LIT_NONE -1 + +#define DW_MLE_CASESENSITIVE 1 + +#define DW_BS_NOBORDER BS_FLAT + +#define DW_POINTER_DEFAULT 0 +#define DW_POINTER_ARROW 32512 +#define DW_POINTER_CLOCK 32514 +#define DW_POINTER_QUESTION 32651 + +/* flag values for dw_messagebox() */ +#define DW_MB_OK MB_OK +#define DW_MB_OKCANCEL MB_OKCANCEL +#define DW_MB_YESNO MB_YESNO +#define DW_MB_YESNOCANCEL MB_YESNOCANCEL + +#define DW_MB_WARNING MB_ICONWARNING +#define DW_MB_ERROR MB_ICONERROR +#define DW_MB_INFORMATION MB_ICONINFORMATION +#define DW_MB_QUESTION MB_ICONQUESTION + +/* Key Modifiers */ +#define KC_CTRL (1) +#define KC_SHIFT (1 << 1) +#define KC_ALT (1 << 2) + +#define STATICCLASSNAME "STATIC" +#define COMBOBOXCLASSNAME "COMBOBOX" +#define LISTBOXCLASSNAME "LISTBOX" +#define BUTTONCLASSNAME "BUTTON" +#define POPUPMENUCLASSNAME "POPUPMENU" +#define EDITCLASSNAME "EDIT" +#define FRAMECLASSNAME "FRAME" +#define SCROLLBARCLASSNAME "SCROLLBAR" + +#define ClassName "dynamicwindows" +#define SplitbarClassName "dwsplitbar" +#define ObjectClassName "dwobjectclass" +#define BrowserClassName "dwbrowserclass" +#define ScrollClassName "dwscrollclass" +#define DefaultFont NULL + +typedef struct _color { + int fore; + int back; + HWND combo, buddy; + int user; + int vcenter; + HWND clickdefault; + HBRUSH hbrush; + HFONT hfont; + char fontname[128]; + WNDPROC pOldProc; + UserData *root; +} ColorInfo; + +typedef struct _notebookpage { + ColorInfo cinfo; + TC_ITEM item; + HWND hwnd; + int realid; +} NotebookPage; + +typedef HANDLE HMTX; +typedef HANDLE HEV; +typedef HANDLE HMOD; +typedef HANDLE HSHM; +typedef HANDLE HICN; + +typedef struct _container { + ColorInfo cinfo; + ULONG *flags; + ULONG columns; + COLORREF odd, even; +} ContainerInfo; + +typedef struct _hpixmap { + unsigned long width, height; + HBITMAP hbm; + HDC hdc; + unsigned long transcolor; + HWND handle; + void *bits; + unsigned long depth; + HFONT font; +} *HPIXMAP; + +typedef HWND HMENUI; +#endif + +typedef struct _item { + /* Item type - Box or Item */ + int type; + /* Handle to Frame or Window */ + HWND hwnd; + /* Width and Height of static size */ + int width, height, origwidth, origheight; + /* Size Type - Static or Expand */ + int hsize, vsize; + /* Padding */ + int pad; + /* Ratio of current item */ + float xratio, yratio; +} Item; + +typedef struct _box { +#if defined(__WIN32__) || defined(WINNT) + ColorInfo cinfo; +#elif defined(__OS2__) || defined(__EMX__) + PFNWP oldproc; + UserData *root; + HWND hwndtitle, hwnd; + int titlebar; +#endif + /* Number of items in the box */ + int count; + /* Box type - horizontal or vertical */ + int type; + /* Padding */ + int pad, parentpad, grouppadx, grouppady; + /* Groupbox */ + HWND grouphwnd; + /* Default item */ + HWND defaultitem; + /* Used as temporary storage in the calculation stage */ + int upx, upy, minheight, minwidth; + /* Ratio in this box */ + float xratio, yratio, parentxratio, parentyratio; + /* Used for calculating individual item ratios */ + int width, height; + /* Any combinations of flags describing the box */ + unsigned long flags; + /* Array of item structures */ + struct _item *items; +} Box; + +typedef struct _bubblebutton { +#if defined(__WIN32__) || defined(WINNT) + ColorInfo cinfo; + int checkbox; + WNDPROC pOldProc; +#endif +#if defined(__OS2__) || defined(__EMX__) + PFNWP pOldProc; + UserData *root; + unsigned long id; + char bubbletext[BUBBLE_HELP_MAX]; +#endif +} BubbleButton; + +#elif defined(__PHOTON__) +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/utsname.h> +/* Photon specific section */ +#include <Pt.h> +#include <Ph.h> +/* which image formats supported */ +#define PX_IMAGE_MODULES +#define PX_GIF_SUPPORT +#define PX_JPG_SUPPORT +#define PX_BMP_SUPPORT +#define PX_PND_SUPPORT +#include <photon/PxImage.h> + +#define TRUE 1 +#define FALSE 0 + +typedef PtWidget_t *pPtWidget_t; +typedef pPtWidget_t HWND; + +typedef unsigned long ULONG; +typedef long LONG; +typedef unsigned short USHORT; +typedef short SHORT; +typedef unsigned short UWORD; +typedef short WORD ; +typedef unsigned char UCHAR; +typedef char CHAR; +typedef unsigned UINT; +typedef int INT; +typedef void *HMTX; +typedef void *HEV; +typedef void *HSHM; +typedef void *HMOD; +typedef PtTreeItem_t *HTREEITEM; +typedef HWND HMENUI; +typedef int DWTID; +typedef unsigned long HICN; + +typedef struct _user_data +{ + struct _user_data *next; + void *data; + char *varname; +} UserData; + +typedef struct _window_data { + UserData *root; + HWND clickdefault; + ULONG flags; + void *data; +} WindowData; + +typedef struct _hpixmap { + unsigned long width, height; + /* ?? *pixmap; */ + HWND handle; +} *HPIXMAP; + +/* colors matching Photon Graphics colors */ +#define DW_CLR_BLACK Pg_BLACK +#define DW_CLR_DARKRED Pg_DRED +#define DW_CLR_DARKGREEN Pg_DGREEN +#define DW_CLR_BROWN Pg_BROWN +#define DW_CLR_DARKBLUE Pg_DBLUE +#define DW_CLR_DARKPINK Pg_PURPLE +#define DW_CLR_DARKCYAN Pg_DCYAN +#define DW_CLR_PALEGRAY Pg_GRAY +#define DW_CLR_DARKGRAY Pg_MGRAY +#define DW_CLR_RED Pg_RED +#define DW_CLR_GREEN Pg_GREEN +#define DW_CLR_YELLOW Pg_YELLOW +#define DW_CLR_BLUE Pg_BLUE +#define DW_CLR_PINK Pg_MAGENTA +#define DW_CLR_CYAN Pg_CYAN +#define DW_CLR_WHITE Pg_WHITE +#define DW_CLR_DEFAULT Pg_GRAY +/* color manipulation macros */ +#define DW_RGB_COLOR (0xF0000000) +#define DW_RGB_TRANSPARENT (0x0F000000) +#define DW_RGB_MASK (0x00FFFFFF) +#define DW_RED_MASK (0x00FF0000) +#define DW_GREEN_MASK (0x0000FF00) +#define DW_BLUE_MASK (0x000000FF) +#define DW_RED_VALUE(a) PgRedValue(a) +#define DW_GREEN_VALUE(a) PgGreenValue(a) +#define DW_BLUE_VALUE(a) PgBluValue(a) +#define DW_RGB(a, b, c) PgRGB( a, b, c ) + +#define DW_DT_LEFT 0 +#define DW_DT_QUERYEXTENT 0 +#define DW_DT_UNDERSCORE 0 +#define DW_DT_STRIKEOUT 0 +#define DW_DT_TEXTATTRS 0 +#define DW_DT_EXTERNALLEADING 0 +#define DW_DT_CENTER 0 +#define DW_DT_RIGHT 0 +#define DW_DT_TOP 0 +#define DW_DT_VCENTER 0 +#define DW_DT_BOTTOM 0 +#define DW_DT_HALFTONE 0 +#define DW_DT_MNEMONIC 0 +#define DW_DT_WORDBREAK 0 +#define DW_DT_ERASERECT 0 + +#define DW_FCF_CLOSEBUTTON Ph_WM_RENDER_CLOSE +#define DW_FCF_TITLEBAR Ph_WM_RENDER_TITLE +#define DW_FCF_SYSMENU 0 +#define DW_FCF_MENU Ph_WM_RENDER_MENU +#define DW_FCF_SIZEBORDER Ph_WM_RENDER_RESIZE +#define DW_FCF_MINBUTTON Ph_WM_RENDER_MIN +#define DW_FCF_MAXBUTTON Ph_WM_RENDER_MAX +#define DW_FCF_MINMAX (Ph_WM_RENDER_MIN|Ph_WM_RENDER_MAX) +#define DW_FCF_VERTSCROLL 0 +#define DW_FCF_HORZSCROLL 0 +#define DW_FCF_DLGBORDER 0 +#define DW_FCF_BORDER Ph_WM_RENDER_BORDER +#define DW_FCF_SHELLPOSITION 0 +#define DW_FCF_TASKLIST 0 +#define DW_FCF_NOBYTEALIGN 0 +#define DW_FCF_NOMOVEWITHOWNER 0 +#define DW_FCF_SYSMODAL 0 +#define DW_FCF_HIDEBUTTON 0 +#define DW_FCF_HIDEMAX 0 +#define DW_FCF_AUTOICON (Ph_WM_RENDER_ASICON | ~Ph_WM_RENDER_ASAPP) +#define DW_FCF_MAXIMIZE 0 +#define DW_FCF_MINIMIZE 0 + +#define DW_CFA_BITMAPORICON 1 +#define DW_CFA_STRING (1 << 1) +#define DW_CFA_ULONG (1 << 2) +#define DW_CFA_TIME (1 << 3) +#define DW_CFA_DATE (1 << 4) +#define DW_CFA_CENTER (1 << 5) +#define DW_CFA_LEFT (1 << 6) +#define DW_CFA_RIGHT (1 << 7) +#define DW_CFA_STRINGANDICON (1 << 8) +#define DW_CFA_HORZSEPARATOR 0 +#define DW_CFA_SEPARATOR 0 + +#define DW_CRA_SELECTED 1 +#define DW_CRA_CURSORED (1 << 1) + +#define DW_LS_MULTIPLESEL 1 + +#define DW_LIT_NONE -1 + +#ifdef MLFSEARCH_CASESENSITIVE +# define DW_MLE_CASESENSITIVE MLFSEARCH_CASESENSITIVE +#else +# define DW_MLE_CASESENSITIVE 0 +#endif + +#define DW_BS_NOBORDER 1 + +#define DW_POINTER_DEFAULT 0 +#define DW_POINTER_ARROW 0 +#define DW_POINTER_CLOCK 0 +#define DW_POINTER_QUESTION 0 + +#define HWND_DESKTOP ((HWND)0) + +/* flag values for dw_messagebox() */ +#define DW_MB_OK (1 << 1) +#define DW_MB_OKCANCEL (1 << 2) +#define DW_MB_YESNO (1 << 3) +#define DW_MB_YESNOCANCEL (1 << 4) + +#define DW_MB_WARNING (1 << 10) +#define DW_MB_ERROR (1 << 11) +#define DW_MB_INFORMATION (1 << 12) +#define DW_MB_QUESTION (1 << 13) + +/* Virtual Key Codes */ +#define VK_LBUTTON 0 +#define VK_RBUTTON 0 +#define VK_CANCEL 0 +#define VK_MBUTTON 0 +#define VK_BACK 0 +#define VK_TAB 0 +#define VK_CLEAR 0 +#define VK_RETURN 0 +#define VK_MENU 0 +#define VK_PAUSE 0 +#define VK_CAPITAL 0 +#define VK_ESCAPE 0 +#define VK_SPACE 0 +#define VK_PRIOR 0 +#define VK_NEXT 0 +#define VK_END 0 +#define VK_HOME 0 +#define VK_LEFT 0 +#define VK_UP 0 +#define VK_RIGHT 0 +#define VK_DOWN 0 +#define VK_SELECT 0 +#define VK_PRINT 0 +#define VK_EXECUTE 0 +#define VK_SNAPSHOT 0 +#define VK_INSERT 0 +#define VK_DELETE 0 +#define VK_HELP 0 +#define VK_LWIN 0 +#define VK_RWIN 0 +#define VK_NUMPAD0 0 +#define VK_NUMPAD1 0 +#define VK_NUMPAD2 0 +#define VK_NUMPAD3 0 +#define VK_NUMPAD4 0 +#define VK_NUMPAD5 0 +#define VK_NUMPAD6 0 +#define VK_NUMPAD7 0 +#define VK_NUMPAD8 0 +#define VK_NUMPAD9 0 +#define VK_MULTIPLY 0 +#define VK_ADD 0 +#define VK_SEPARATOR 0 +#define VK_SUBTRACT 0 +#define VK_DECIMAL 0 +#define VK_DIVIDE 0 +#define VK_F1 0 +#define VK_F2 0 +#define VK_F3 0 +#define VK_F4 0 +#define VK_F5 0 +#define VK_F6 0 +#define VK_F7 0 +#define VK_F8 0 +#define VK_F9 0 +#define VK_F10 0 +#define VK_F11 0 +#define VK_F12 0 +#define VK_F13 0 +#define VK_F14 0 +#define VK_F15 0 +#define VK_F16 0 +#define VK_F17 0 +#define VK_F18 0 +#define VK_F19 0 +#define VK_F20 0 +#define VK_F21 0 +#define VK_F22 0 +#define VK_F23 0 +#define VK_F24 0 +#define VK_NUMLOCK 0 +#define VK_SCROLL 0 +#define VK_LSHIFT 0 +#define VK_RSHIFT 0 +#define VK_LCONTROL 0 +#define VK_RCONTROL 0 +#define VK_LMENU 0 +#define VK_RMENU 0 + +/* Key Modifiers */ +#define KC_CTRL (1) +#define KC_SHIFT (1 << 1) +#define KC_ALT (1 << 2) + +#else +/* GTK Specific section */ +#include <gtk/gtk.h> +#ifdef GDK_WINDOWING_X11 +# include <gdk/gdkx.h> +#else +# include <gdk/gdk.h> +#endif +#include <gdk/gdkprivate.h> +#include <gdk/gdkkeysyms.h> +#include <pthread.h> +#if !defined(GDK_WINDOWING_WIN32) +# include <dlfcn.h> +#endif + +#define DW_DT_LEFT 1 +#define DW_DT_UNDERSCORE (1 << 1) +#define DW_DT_STRIKEOUT (1 << 2) +#define DW_DT_CENTER (1 << 3) +#define DW_DT_RIGHT (1 << 4) +#define DW_DT_TOP (1 << 5) +#define DW_DT_VCENTER (1 << 6) +#define DW_DT_BOTTOM (1 << 7) +#define DW_DT_HALFTONE (1 << 8) +#define DW_DT_MNEMONIC (1 << 9) +#define DW_DT_WORDBREAK (1 << 10) +#define DW_DT_ERASERECT (1 << 11) + +/* these don't exist under gtk, so make them dummy entries */ +#define DW_DT_QUERYEXTENT 0 +#define DW_DT_TEXTATTRS 0 +#define DW_DT_EXTERNALLEADING 0 + +#define DW_FCF_TITLEBAR 1 +#define DW_FCF_SYSMENU (1 << 1) +#define DW_FCF_MENU (1 << 2) +#define DW_FCF_SIZEBORDER (1 << 3) +#define DW_FCF_MINBUTTON (1 << 4) +#define DW_FCF_MAXBUTTON (1 << 5) +#define DW_FCF_MINMAX (1 << 6) +#define DW_FCF_VERTSCROLL (1 << 7) +#define DW_FCF_HORZSCROLL (1 << 8) +#define DW_FCF_DLGBORDER (1 << 9) +#define DW_FCF_BORDER (1 << 10) +#define DW_FCF_SHELLPOSITION (1 << 11) +#define DW_FCF_TASKLIST (1 << 12) +#define DW_FCF_NOBYTEALIGN (1 << 13) +#define DW_FCF_NOMOVEWITHOWNER (1 << 14) +#define DW_FCF_SYSMODAL (1 << 15) +#define DW_FCF_HIDEBUTTON (1 << 16) +#define DW_FCF_HIDEMAX (1 << 17) +#define DW_FCF_AUTOICON (1 << 18) +#define DW_FCF_MAXIMIZE (1 << 19) +#define DW_FCF_MINIMIZE (1 << 20) +#define DW_FCF_CLOSEBUTTON (1 << 21) + +#define DW_CFA_BITMAPORICON 1 +#define DW_CFA_STRING (1 << 1) +#define DW_CFA_ULONG (1 << 2) +#define DW_CFA_TIME (1 << 3) +#define DW_CFA_DATE (1 << 4) +#define DW_CFA_CENTER (1 << 5) +#define DW_CFA_LEFT (1 << 6) +#define DW_CFA_RIGHT (1 << 7) +#define DW_CFA_HORZSEPARATOR (1 << 8) +#define DW_CFA_SEPARATOR (1 << 9) +#define DW_CFA_STRINGANDICON (1 << 10) + +#define DW_CRA_SELECTED 1 +#define DW_CRA_CURSORED (1 << 1) + +#define DW_LS_MULTIPLESEL 1 + +#define DW_LIT_NONE -1 + +#define DW_MLE_CASESENSITIVE 1 + +#define DW_BS_NOBORDER 1 + +#define DW_POINTER_DEFAULT 0 +#define DW_POINTER_ARROW GDK_TOP_LEFT_ARROW +#define DW_POINTER_CLOCK GDK_WATCH +#define DW_POINTER_QUESTION GDK_QUESTION_ARROW + +#define HWND_DESKTOP ((HWND)0) + +/* flag values for dw_messagebox() */ +#define DW_MB_OK (1 << 1) +#define DW_MB_OKCANCEL (1 << 2) +#define DW_MB_YESNO (1 << 3) +#define DW_MB_YESNOCANCEL (1 << 4) + +#define DW_MB_WARNING (1 << 10) +#define DW_MB_ERROR (1 << 11) +#define DW_MB_INFORMATION (1 << 12) +#define DW_MB_QUESTION (1 << 13) + +/* Virtual Key Codes */ +#if GTK_MAJOR_VERSION > 2 +#define VK_LBUTTON GDK_KEY_Pointer_Button1 +#define VK_RBUTTON GDK_KEY_Pointer_Button3 +#define VK_CANCEL GDK_KEY_Cancel +#define VK_MBUTTON GDK_KEY_Pointer_Button2 +#define VK_BACK GDK_KEY_BackSpace +#define VK_TAB GDK_KEY_Tab +#define VK_CLEAR GDK_KEY_Clear +#define VK_RETURN GDK_KEY_Return +#define VK_MENU GDK_KEY_Menu +#define VK_PAUSE GDK_KEY_Pause +#define VK_CAPITAL GDK_KEY_Caps_Lock +#define VK_ESCAPE GDK_KEY_Escape +#define VK_SPACE GDK_KEY_space +#define VK_PRIOR GDK_KEY_Page_Up +#define VK_NEXT GDK_KEY_Page_Down +#define VK_END GDK_KEY_End +#define VK_HOME GDK_KEY_Home +#define VK_LEFT GDK_KEY_Left +#define VK_UP GDK_KEY_Up +#define VK_RIGHT GDK_KEY_Right +#define VK_DOWN GDK_KEY_Down +#define VK_SELECT GDK_KEY_Select +#define VK_PRINT GDK_KEY_Sys_Req +#define VK_EXECUTE GDK_KEY_Execute +#define VK_SNAPSHOT GDK_KEY_Print +#define VK_INSERT GDK_KEY_Insert +#define VK_DELETE GDK_KEY_Delete +#define VK_HELP GDK_KEY_Help +#define VK_LWIN GDK_KEY_Super_L +#define VK_RWIN GDK_KEY_Super_R +#define VK_NUMPAD0 GDK_KEY_KP_0 +#define VK_NUMPAD1 GDK_KEY_KP_1 +#define VK_NUMPAD2 GDK_KEY_KP_2 +#define VK_NUMPAD3 GDK_KEY_KP_3 +#define VK_NUMPAD4 GDK_KEY_KP_4 +#define VK_NUMPAD5 GDK_KEY_KP_5 +#define VK_NUMPAD6 GDK_KEY_KP_6 +#define VK_NUMPAD7 GDK_KEY_KP_7 +#define VK_NUMPAD8 GDK_KEY_KP_8 +#define VK_NUMPAD9 GDK_KEY_KP_9 +#define VK_MULTIPLY GDK_KEY_KP_Multiply +#define VK_ADD GDK_KEY_KP_Add +#define VK_SEPARATOR GDK_KEY_KP_Separator +#define VK_SUBTRACT GDK_KEY_KP_Subtract +#define VK_DECIMAL GDK_KEY_KP_Decimal +#define VK_DIVIDE GDK_KEY_KP_Divide +#define VK_F1 GDK_KEY_F1 +#define VK_F2 GDK_KEY_F2 +#define VK_F3 GDK_KEY_F3 +#define VK_F4 GDK_KEY_F4 +#define VK_F5 GDK_KEY_F5 +#define VK_F6 GDK_KEY_F6 +#define VK_F7 GDK_KEY_F7 +#define VK_F8 GDK_KEY_F8 +#define VK_F9 GDK_KEY_F9 +#define VK_F10 GDK_KEY_F10 +#define VK_F11 GDK_KEY_F11 +#define VK_F12 GDK_KEY_F12 +#define VK_F13 GDK_KEY_F13 +#define VK_F14 GDK_KEY_F14 +#define VK_F15 GDK_KEY_F15 +#define VK_F16 GDK_KEY_F16 +#define VK_F17 GDK_KEY_F17 +#define VK_F18 GDK_KEY_F18 +#define VK_F19 GDK_KEY_F19 +#define VK_F20 GDK_KEY_F20 +#define VK_F21 GDK_KEY_F21 +#define VK_F22 GDK_KEY_F22 +#define VK_F23 GDK_KEY_F23 +#define VK_F24 GDK_KEY_F24 +#define VK_NUMLOCK GDK_KEY_Num_Lock +#define VK_SCROLL GDK_KEY_Scroll_Lock +#define VK_LSHIFT GDK_KEY_Shift_L +#define VK_RSHIFT GDK_KEY_Shift_R +#define VK_LCONTROL GDK_KEY_Control_L +#define VK_RCONTROL GDK_KEY_Control_R +#define VK_LMENU GDK_KEY_Menu +#define VK_RMENU GDK_KEY_Menu + +#else +#define VK_LBUTTON GDK_Pointer_Button1 +#define VK_RBUTTON GDK_Pointer_Button3 +#define VK_CANCEL GDK_Cancel +#define VK_MBUTTON GDK_Pointer_Button2 +#define VK_BACK GDK_BackSpace +#define VK_TAB GDK_Tab +#define VK_CLEAR GDK_Clear +#define VK_RETURN GDK_Return +#define VK_MENU GDK_Menu +#define VK_PAUSE GDK_Pause +#define VK_CAPITAL GDK_Caps_Lock +#define VK_ESCAPE GDK_Escape +#define VK_SPACE GDK_space +#define VK_PRIOR GDK_Page_Up +#define VK_NEXT GDK_Page_Down +#define VK_END GDK_End +#define VK_HOME GDK_Home +#define VK_LEFT GDK_Left +#define VK_UP GDK_Up +#define VK_RIGHT GDK_Right +#define VK_DOWN GDK_Down +#define VK_SELECT GDK_Select +#define VK_PRINT GDK_Sys_Req +#define VK_EXECUTE GDK_Execute +#define VK_SNAPSHOT GDK_Print +#define VK_INSERT GDK_Insert +#define VK_DELETE GDK_Delete +#define VK_HELP GDK_Help +#define VK_LWIN GDK_Super_L +#define VK_RWIN GDK_Super_R +#define VK_NUMPAD0 GDK_KP_0 +#define VK_NUMPAD1 GDK_KP_1 +#define VK_NUMPAD2 GDK_KP_2 +#define VK_NUMPAD3 GDK_KP_3 +#define VK_NUMPAD4 GDK_KP_4 +#define VK_NUMPAD5 GDK_KP_5 +#define VK_NUMPAD6 GDK_KP_6 +#define VK_NUMPAD7 GDK_KP_7 +#define VK_NUMPAD8 GDK_KP_8 +#define VK_NUMPAD9 GDK_KP_9 +#define VK_MULTIPLY GDK_KP_Multiply +#define VK_ADD GDK_KP_Add +#define VK_SEPARATOR GDK_KP_Separator +#define VK_SUBTRACT GDK_KP_Subtract +#define VK_DECIMAL GDK_KP_Decimal +#define VK_DIVIDE GDK_KP_Divide +#define VK_F1 GDK_F1 +#define VK_F2 GDK_F2 +#define VK_F3 GDK_F3 +#define VK_F4 GDK_F4 +#define VK_F5 GDK_F5 +#define VK_F6 GDK_F6 +#define VK_F7 GDK_F7 +#define VK_F8 GDK_F8 +#define VK_F9 GDK_F9 +#define VK_F10 GDK_F10 +#define VK_F11 GDK_F11 +#define VK_F12 GDK_F12 +#define VK_F13 GDK_F13 +#define VK_F14 GDK_F14 +#define VK_F15 GDK_F15 +#define VK_F16 GDK_F16 +#define VK_F17 GDK_F17 +#define VK_F18 GDK_F18 +#define VK_F19 GDK_F19 +#define VK_F20 GDK_F20 +#define VK_F21 GDK_F21 +#define VK_F22 GDK_F22 +#define VK_F23 GDK_F23 +#define VK_F24 GDK_F24 +#define VK_NUMLOCK GDK_Num_Lock +#define VK_SCROLL GDK_Scroll_Lock +#define VK_LSHIFT GDK_Shift_L +#define VK_RSHIFT GDK_Shift_R +#define VK_LCONTROL GDK_Control_L +#define VK_RCONTROL GDK_Control_R +#define VK_LMENU GDK_Menu +#define VK_RMENU GDK_Menu +#endif + +/* Key Modifiers */ +#define KC_CTRL GDK_CONTROL_MASK +#define KC_SHIFT GDK_SHIFT_MASK +#define KC_ALT GDK_MOD1_MASK + +typedef GtkWidget *HWND; +#ifndef _ENVRNMNT_H +typedef unsigned long ULONG; +#endif +typedef long LONG; +typedef unsigned short USHORT; +typedef short SHORT; +typedef unsigned short UWORD; +typedef short WORD ; +typedef unsigned char UCHAR; +typedef char CHAR; +typedef unsigned UINT; +typedef int INT; +typedef pthread_mutex_t *HMTX; +typedef struct _dw_unix_event { + pthread_mutex_t mutex; + pthread_cond_t event; + pthread_t thread; + int alive; + int posted; +} *HEV; +typedef pthread_t DWTID; +typedef void * HMOD; +struct _dw_unix_shm { + int fd; + char *path; + int sid; + int size; +}; + +typedef struct _hpixmap { + unsigned long width, height; + HWND handle; + char *font; +#if GTK_MAJOR_VERSION > 1 + GdkPixbuf *pixbuf; /* the actual image */ +#endif +#if GTK_MAJOR_VERSION > 2 + cairo_surface_t *image; /* Going to have dual storage for now */ +#else + GdkPixmap *pixmap; /* the actual image */ + GdkBitmap *bitmap; /* if not null, the image mask representing the transparency mask */ + void *image; /* Opaque handle to a cairo_surface_t for printing */ +#endif +} *HPIXMAP; + +typedef GtkWidget *HMENUI; +typedef void *HTREEITEM; +typedef void *HSHM; +typedef void *HICN; + +typedef struct _resource_struct { + long resource_max, *resource_id; + char **resource_data; +} DWResources; + +#if !defined(DW_RESOURCES) || defined(BUILD_DLL) +static DWResources _resources = { 0, 0, 0 }; +#else +extern DWResources _resources; +#endif + +#endif + +#if !defined(__OS2__) && !defined(__EMX__) +typedef struct _CDATE +{ + UCHAR day; + UCHAR month; + USHORT year; +} CDATE; +typedef CDATE *PCDATE; + +typedef struct _CTIME +{ + UCHAR hours; + UCHAR minutes; + UCHAR seconds; + UCHAR ucReserved; +} CTIME; +typedef CTIME *PCTIME; +#endif + +#if defined(__OS2__) || (defined(__WIN32__) && !defined(GDK_WINDOWING_WIN32)) || (defined(WINNT) && !defined(GDK_WINDOWING_WIN32)) || defined(__EMX__) +typedef unsigned long DWTID; +#endif + +typedef struct _dwenv { + /* Operating System Name and DW Build Date/Time */ + char osName[30], buildDate[30], buildTime[30]; + /* Versions and builds */ + short MajorVersion, MinorVersion, MajorBuild, MinorBuild; + /* Dynamic Window version */ + short DWMajorVersion, DWMinorVersion, DWSubVersion; +} DWEnv; + + +typedef struct _dwexpose { + int x, y; + int width, height; +} DWExpose; + +typedef struct _dwdialog { + HEV eve; + int done; + int method; + void *data, *result; +} DWDialog; + +typedef void *HPRINT; + +#define DW_SIGNAL_FUNC(a) ((void *)a) + +#define DW_DESKTOP HWND_DESKTOP +#define DW_MINIMIZED 1 + +#define DW_BUTTON1_MASK 1 +#define DW_BUTTON2_MASK (1 << 1) +#define DW_BUTTON3_MASK (1 << 2) + +#define DW_EXEC_CON 0 +#define DW_EXEC_GUI 1 + +#define DW_FILE_OPEN 0 +#define DW_FILE_SAVE 1 +#define DW_DIRECTORY_OPEN 2 + +#define DW_HORZ 0 +#define DW_VERT 1 + +#define DW_TIMEOUT_INFINITE ((unsigned long)-1) + +/* Obsolete, should disappear sometime */ +#define BOXHORZ DW_HORZ +#define BOXVERT DW_VERT + +#define DW_SCROLL_UP 0 +#define DW_SCROLL_DOWN 1 +#define DW_SCROLL_TOP 2 +#define DW_SCROLL_BOTTOM 3 + +/* return values for dw_messagebox() */ +#define DW_MB_RETURN_OK 0 +#define DW_MB_RETURN_YES 1 +#define DW_MB_RETURN_NO 0 +#define DW_MB_RETURN_CANCEL 2 + +#define DW_PIXMAP_WIDTH(x) (x ? x->width : 0) +#define DW_PIXMAP_HEIGHT(x) (x ? x->height : 0) + +#if !defined(__PHOTON__) +#define DW_RGB_COLOR (0xF0000000) +#define DW_RGB_TRANSPARENT (0x0F000000) +#define DW_RGB_MASK (0x00FFFFFF) +#define DW_RED_MASK (0x000000FF) +#define DW_GREEN_MASK (0x0000FF00) +#define DW_BLUE_MASK (0x00FF0000) +#define DW_RED_VALUE(a) (a & DW_RED_MASK) +#define DW_GREEN_VALUE(a) ((a & DW_GREEN_MASK) >> 8) +#define DW_BLUE_VALUE(a) ((a & DW_BLUE_MASK) >> 16) +#define DW_RGB(a, b, c) (0xF0000000 | (a) | (b) << 8 | (c) << 16) +#endif + +#define DW_MENU_SEPARATOR "" +#define DW_NOMENU 0 +#define DW_MENU_AUTO 0 +#define DW_MENU_POPUP (unsigned long)-1 + +#define DW_PERCENT_INDETERMINATE ((unsigned int)-1) + +/* Return value error codes */ +#define DW_ERROR_NONE 0 +#define DW_ERROR_GENERAL 1 +#define DW_ERROR_TIMEOUT 2 +#define DW_ERROR_NON_INIT 3 +#define DW_ERROR_NO_MEM 4 +#define DW_ERROR_INTERRUPT 5 +#define DW_ERROR_UNKNOWN -1 + +/* Embedded HTML actions */ +#define DW_HTML_GOBACK 0 +#define DW_HTML_GOFORWARD 1 +#define DW_HTML_GOHOME 2 +#define DW_HTML_SEARCH 3 +#define DW_HTML_RELOAD 4 +#define DW_HTML_STOP 5 +#define DW_HTML_PRINT 6 + +/* Drawing flags... used for Arc currently */ +#define DW_DRAW_DEFAULT 0 +#define DW_DRAW_FILL 1 +#define DW_DRAW_FULL (1 << 1) + + +/* 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 +#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 +#define DW_INT_TO_POINTER(a) ((void *)a) +#define DW_POINTER_TO_INT(a) ((int)a) +#define DW_UINT_TO_POINTER(a) ((void *)a) +#define DW_POINTER_TO_UINT(a) ((unsigned int)a) +#endif + +#ifndef API +#define API +#endif + +#define DWSIGNAL API + +/* Let other APIs know what types we've defined, + * Regina REXX in particular, on Unix. + */ +#define ULONG_TYPEDEFED 1 +#define LONG_TYPEDEFED 1 +#define USHORT_TYPEDEFED 1 +#define SHORT_TYPEDEFED 1 +#define UWORD_TYPEDEFED 1 +#define WORD_TYPEDEFED 1 +#define UCHAR_TYPEDEFED 1 +#define CHAR_TYPEDEFED 1 +#define UINT_TYPEDEFED 1 +#define INT_TYPEDEFED 1 + +/* Public function prototypes */ +void API dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad); +void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad); +void API dw_box_pack_at_index(HWND box, HWND item, int index, int width, int height, int hsize, int vsize, int pad); +#if !defined(__OS2__) && !defined(__WIN32__) && !defined(__EMX__) && !defined(__MAC__) +int API dw_int_init(DWResources *res, int newthread, int *argc, char **argv[]); +#define dw_init(a, b, c) dw_int_init(&_resources, a, &b, &c) +#else +int API dw_init(int newthread, int argc, char *argv[]); +#endif +void API dw_main(void); +void API dw_main_sleep(int seconds); +void API dw_main_iteration(void); +void API dw_free(void *ptr); +int API dw_window_show(HWND handle); +int API dw_window_hide(HWND handle); +int API dw_window_minimize(HWND handle); +int API dw_window_raise(HWND handle); +int API dw_window_lower(HWND handle); +int API dw_window_destroy(HWND handle); +void API dw_window_redraw(HWND handle); +int API dw_window_set_font(HWND handle, char *fontname); +char * API dw_window_get_font(HWND handle); +int API dw_window_set_color(HWND handle, unsigned long fore, unsigned long back); +HWND API dw_window_new(HWND hwndOwner, char *title, unsigned long flStyle); +HWND API dw_box_new(int type, int pad); +HWND API dw_scrollbox_new(int type, int pad); +int API dw_scrollbox_get_pos( HWND handle, int orient ); +int API dw_scrollbox_get_range( HWND handle, int orient ); +HWND API dw_groupbox_new(int type, int pad, char *title); +HWND API dw_mdi_new(unsigned long id); +HWND API dw_bitmap_new(unsigned long id); +HWND API dw_bitmapbutton_new(char *text, unsigned long id); +HWND API dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename); +HWND API dw_bitmapbutton_new_from_data(char *text, unsigned long id, char *str, int len); +HWND API dw_container_new(unsigned long id, int multi); +HWND API dw_tree_new(unsigned long id); +HWND API dw_text_new(char *text, unsigned long id); +HWND API dw_status_text_new(char *text, unsigned long id); +HWND API dw_mle_new(unsigned long id); +HWND API dw_entryfield_new(char *text, unsigned long id); +HWND API dw_entryfield_password_new(char *text, ULONG id); +HWND API dw_combobox_new(char *text, unsigned long id); +HWND API dw_button_new(char *text, unsigned long id); +HWND API dw_spinbutton_new(char *text, unsigned long id); +HWND API dw_radiobutton_new(char *text, ULONG id); +HWND API dw_percent_new(unsigned long id); +HWND API dw_slider_new(int vertical, int increments, ULONG id); +HWND API dw_scrollbar_new(int vertical, ULONG id); +HWND API dw_checkbox_new(char *text, unsigned long id); +HWND API dw_listbox_new(unsigned long id, int multi); +void API dw_listbox_append(HWND handle, char *text); +void API dw_listbox_insert(HWND handle, char *text, int pos); +void API dw_listbox_list_append(HWND handle, char **text, int count); +void API dw_listbox_clear(HWND handle); +int API dw_listbox_count(HWND handle); +void API dw_listbox_set_top(HWND handle, int top); +void API dw_listbox_select(HWND handle, int index, int state); +void API dw_listbox_delete(HWND handle, int index); +void API dw_listbox_get_text(HWND handle, unsigned int index, char *buffer, unsigned int length); +void API dw_listbox_set_text(HWND handle, unsigned int index, char *buffer); +int API dw_listbox_selected(HWND handle); +int API dw_listbox_selected_multi(HWND handle, int where); +void API dw_percent_set_pos(HWND handle, unsigned int position); +unsigned int API dw_slider_get_pos(HWND handle); +void API dw_slider_set_pos(HWND handle, unsigned int position); +unsigned int API dw_scrollbar_get_pos(HWND handle); +void API dw_scrollbar_set_pos(HWND handle, unsigned int position); +void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible); +void API dw_window_set_pos(HWND handle, long x, long y); +void API dw_window_set_size(HWND handle, unsigned long width, unsigned long height); +void API dw_window_set_pos_size(HWND handle, long x, long y, unsigned long width, unsigned long height); +void API dw_window_get_pos_size(HWND handle, long *x, long *y, unsigned long *width, unsigned long *height); +void API dw_window_set_style(HWND handle, unsigned long style, unsigned long mask); +void API dw_window_set_icon(HWND handle, HICN icon); +void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename); +void API dw_window_set_bitmap_from_data(HWND handle, unsigned long id, char *data, int len); +char * API dw_window_get_text(HWND handle); +void API dw_window_set_text(HWND handle, char *text); +int API dw_window_set_border(HWND handle, int border); +void API dw_window_disable(HWND handle); +void API dw_window_enable(HWND handle); +void API dw_window_capture(HWND handle); +void API dw_window_release(void); +void API dw_window_reparent(HWND handle, HWND newparent); +void API dw_window_set_pointer(HWND handle, int pointertype); +void API dw_window_default(HWND window, HWND defaultitem); +void API dw_window_click_default(HWND window, HWND next); +unsigned int API dw_mle_import(HWND handle, char *buffer, int startpoint); +void API dw_mle_export(HWND handle, char *buffer, int startpoint, int length); +void API dw_mle_get_size(HWND handle, unsigned long *bytes, unsigned long *lines); +void API dw_mle_delete(HWND handle, int startpoint, int length); +void API dw_mle_clear(HWND handle); +void API dw_mle_freeze(HWND handle); +void API dw_mle_thaw(HWND handle); +void API dw_mle_set_cursor(HWND handle, int point); +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); +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); +void API dw_entryfield_set_limit(HWND handle, ULONG limit); +long API dw_spinbutton_get_pos(HWND handle); +int API dw_checkbox_get(HWND handle); +void API dw_checkbox_set(HWND handle, int value); +HTREEITEM API dw_tree_insert(HWND handle, char *title, HICN icon, HTREEITEM parent, void *itemdata); +HTREEITEM API dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, HICN icon, HTREEITEM parent, void *itemdata); +void API dw_tree_clear(HWND handle); +void API dw_tree_item_delete(HWND handle, HTREEITEM item); +void API dw_tree_item_change(HWND handle, HTREEITEM item, char *title, HICN icon); +void API dw_tree_item_expand(HWND handle, HTREEITEM item); +void API dw_tree_item_collapse(HWND handle, HTREEITEM item); +void API dw_tree_item_select(HWND handle, HTREEITEM item); +void API dw_tree_item_set_data(HWND handle, HTREEITEM item, void *itemdata); +void * API dw_tree_item_get_data(HWND handle, HTREEITEM item); +char * API dw_tree_get_title(HWND handle, HTREEITEM item); +HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item); +int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator); +HICN API dw_icon_load(unsigned long module, unsigned long id); +HICN API dw_icon_load_from_file(char *filename); +HICN API dw_icon_load_from_data(char *data, int len); +void API dw_icon_free(HICN handle); +void * API dw_container_alloc(HWND handle, int rowcount); +void API dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data); +void API dw_container_change_item(HWND handle, int column, int row, void *data); +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_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); +char * API dw_container_query_start(HWND handle, unsigned long flags); +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_delete_row(HWND handle, char *text); +void API dw_container_optimize(HWND handle); +void API dw_container_set_stripe(HWND handle, unsigned long oddcolor, unsigned long evencolor); +int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count); +void API dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data); +void API dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, HICN icon); +void API dw_filesystem_change_item(HWND handle, int column, int row, void *data); +void API dw_filesystem_change_file(HWND handle, int row, char *filename, HICN icon); +int API dw_container_get_column_type(HWND handle, int column); +int API dw_filesystem_get_column_type(HWND handle, int column); +void API dw_taskbar_insert(HWND handle, HICN icon, char *bubbletext); +void API dw_taskbar_delete(HWND handle, HICN icon); +int API dw_screen_width(void); +int API dw_screen_height(void); +unsigned long API dw_color_depth_get(void); +HWND API dw_notebook_new(unsigned long id, int top); +unsigned long API dw_notebook_page_new(HWND handle, unsigned long flags, int front); +void API dw_notebook_page_destroy(HWND handle, unsigned int pageid); +void API dw_notebook_page_set_text(HWND handle, unsigned long pageid, char *text); +void API dw_notebook_page_set_status_text(HWND handle, unsigned long pageid, char *text); +void API dw_notebook_page_set(HWND handle, unsigned int pageid); +unsigned long API dw_notebook_page_get(HWND handle); +void API dw_notebook_pack(HWND handle, unsigned long pageid, HWND page); +HWND API dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id); +void API dw_splitbar_set(HWND handle, float percent); +float API dw_splitbar_get(HWND handle); +HMENUI API dw_menu_new(unsigned long id); +HMENUI API dw_menubar_new(HWND location); +HWND API dw_menu_append_item(HMENUI menu, char *title, unsigned long id, unsigned long flags, int end, int check, HMENUI submenu); +#ifdef INCOMPLETE +void API dw_menu_delete_item(HMENUI menu, unsigned long id); +#endif +void API dw_menu_item_set_check(HMENUI menu, unsigned long id, int check); +void API dw_menu_item_set_state( HMENUI menux, unsigned long id, unsigned long state); +void API dw_menu_popup(HMENUI *menu, HWND parent, int x, int y); +void API dw_menu_destroy(HMENUI *menu); +void API dw_pointer_query_pos(long *x, long *y); +void API dw_pointer_set_pos(long x, long y); +void API dw_window_function(HWND handle, void *function, void *data); +HWND API dw_window_from_id(HWND handle, int id); +HMTX API dw_mutex_new(void); +void API dw_mutex_close(HMTX mutex); +void API dw_mutex_lock(HMTX mutex); +int API dw_mutex_trylock(HMTX mutex); +void API dw_mutex_unlock(HMTX mutex); +HEV API dw_event_new(void); +int API dw_event_reset(HEV eve); +int API dw_event_post(HEV eve); +int API dw_event_wait(HEV eve, unsigned long timeout); +int API dw_event_close (HEV *eve); +DWTID API dw_thread_new(void *func, void *data, int stack); +void API dw_thread_end(void); +DWTID API dw_thread_id(void); +void API dw_exit(int exitcode); +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); +unsigned long API dw_color_choose(unsigned long value); +char * API dw_font_choose(char *currfont); +void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y); +void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2); +void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height); +void API dw_draw_polygon(HWND handle, HPIXMAP pixmap, int fill, int npoints, int *x, int *y); +void API dw_draw_arc(HWND handle, HPIXMAP pixmap, int flags, int xorigin, int yorigin, int x1, int y1, int x2, int y2); +void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text); +void API dw_font_text_extents_get(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height); +void API dw_font_set_default(char *fontname); +void API dw_flush(void); +void API dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc); +int API dw_pixmap_stretch_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc, int srcwidth, int srcheight); +HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth); +HPIXMAP API dw_pixmap_new_from_file(HWND handle, char *filename); +HPIXMAP API dw_pixmap_new_from_data(HWND handle, char *data, int len); +HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id); +void API dw_pixmap_set_transparent_color( HPIXMAP pixmap, ULONG color ); +int API dw_pixmap_set_font(HPIXMAP pixmap, char *fontname); +void API dw_pixmap_destroy(HPIXMAP pixmap); +void API dw_beep(int freq, int dur); +void API dw_debug(char *format, ...); +int API dw_messagebox(char *title, int flags, char *format, ...); +void API dw_environment_query(DWEnv *env); +int API dw_exec(char *program, int type, char **params); +int API dw_browse(char *url); +char * API dw_file_browse(char *title, char *defpath, char *ext, int flags); +char * API dw_user_dir(void); +DWDialog * API dw_dialog_new(void *data); +int API dw_dialog_dismiss(DWDialog *dialog, void *result); +void * API dw_dialog_wait(DWDialog *dialog); +void API dw_window_set_data(HWND window, char *dataname, void *data); +void * API dw_window_get_data(HWND window, char *dataname); +int API dw_module_load(char *name, HMOD *handle); +int API dw_module_symbol(HMOD handle, char *name, void**func); +int API dw_module_close(HMOD handle); +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_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); +HEV API dw_named_event_new(char *name); +HEV API dw_named_event_get(char *name); +int API dw_named_event_reset(HEV eve); +int API dw_named_event_post(HEV eve); +int API dw_named_event_wait(HEV eve, unsigned long timeout); +int API dw_named_event_close(HEV eve); +HSHM API dw_named_memory_new(void **dest, int size, char *name); +HSHM API dw_named_memory_get(void **dest, int size, char *name); +int API dw_named_memory_free(HSHM handle, void *ptr); +void API dw_html_action(HWND hwnd, int action); +int API dw_html_raw(HWND hwnd, char *string); +int API dw_html_url(HWND hwnd, char *url); +HWND API dw_html_new(unsigned long id); +char * API dw_clipboard_get_text(void); +void API dw_clipboard_set_text( char *str, int len ); +HWND API dw_calendar_new(unsigned long id); +void API dw_calendar_set_date( HWND window, unsigned int year, unsigned int month, unsigned int day ); +void API dw_calendar_get_date( HWND window, unsigned int *year, unsigned int *month, unsigned int *day ); +HPRINT API dw_print_new(char *jobname, unsigned long flags, unsigned int pages, void *drawfunc, void *drawdata); +int API dw_print_run(HPRINT print, unsigned long flags); +void API dw_print_cancel(HPRINT print); + +#endif
--- a/install.c Fri Feb 18 09:04:25 2011 -0600 +++ b/install.c Sun Nov 13 07:22:43 2011 -0600 @@ -1864,7 +1864,7 @@ for(j=1;j<INSTALLER_PACKAGE_COUNT;j++) dw_listbox_append(listbox, INSTALLER_PACKAGES[j]); - dw_window_set_usize(entrywindow, 450, 350); + dw_window_set_size(entrywindow, 450, 350); dw_window_show(entrywindow); @@ -1930,21 +1930,20 @@ dw_signal_connect(okbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(generic_cancel), (void *)param); - dw_window_set_usize(infowindow, 600, 400); + dw_window_set_size(infowindow, 600, 400); - dw_mle_set(mle, 0); + dw_mle_set_cursor(mle, 0); dw_window_show(infowindow); } void update_percent(void) { - static int pixels = 0; ULONG sliderpos = 0; - if(!no_update && files && (pixels = dw_percent_query_range(hwndper))) + if(!no_update && files) { - sliderpos = (int)(((float)current_file/(float)files)*pixels); + sliderpos = (int)(((float)current_file/(float)files)*100); dw_percent_set_pos(hwndper, sliderpos); } }
--- a/instsup.c Fri Feb 18 09:04:25 2011 -0600 +++ b/instsup.c Sun Nov 13 07:22:43 2011 -0600 @@ -42,7 +42,7 @@ /* This should return the current color depth */ ULONG color_depth(void) { - return dw_color_depth(); + return dw_color_depth_get(); } /* This should return true for WinNT/2K/XP and false on Win9x */
--- a/os2/dw.c Fri Feb 18 09:04:25 2011 -0600 +++ b/os2/dw.c Sun Nov 13 07:22:43 2011 -0600 @@ -1,8853 +1,11227 @@ -/* - * Dynamic Windows: - * A GTK like implementation of the PM GUI - * - * (C) 2000-2003 Brian Smith <dbsoft@technologist.com> - * (C) 2000 Achim Hasenmueller <achimha@innotek.de> - * (C) 2000 Peter Nielsen <peter@pmview.com> - * (C) 1998 Sergey I. Yevtushenko (some code borrowed from cell toolkit) - * - */ -#define INCL_DOS -#define INCL_DOSERRORS -#define INCL_WIN -#define INCL_GPI - -#include <os2.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdarg.h> -#include <stddef.h> -#include <ctype.h> -#include <process.h> -#include <time.h> -#include <io.h> -#ifndef __EMX__ -#include <direct.h> -#endif -#include <sys/time.h> -#include "dw.h" - -#define QWP_USER 0 - -MRESULT EXPENTRY _run_event(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); -void _dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad, char *functionname); -void _dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad, char *functionname); -void _free_menu_data(HWND menu); - -char ClassName[] = "dynamicwindows"; -char SplitbarClassName[] = "dwsplitbar"; -char *DefaultFont = "9.WarpSans"; - -HAB dwhab = 0; -HMQ dwhmq = 0; -DWTID _dwtid = 0; -LONG _foreground = 0xAAAAAA, _background = DW_CLR_DEFAULT; - -HWND hwndApp = NULLHANDLE, hwndBubble = NULLHANDLE, hwndBubbleLast = NULLHANDLE, hwndEmph = NULLHANDLE; -PRECORDCORE pCore = NULL, pCoreEmph = NULL; -ULONG aulBuffer[4]; -HWND lasthcnr = 0, lastitem = 0, popup = 0, desktop; - -unsigned long _colors[] = { - CLR_BLACK, - CLR_DARKRED, - CLR_DARKGREEN, - CLR_BROWN, - CLR_DARKBLUE, - CLR_DARKPINK, - CLR_DARKCYAN, - CLR_PALEGRAY, - CLR_DARKGRAY, - CLR_RED, - CLR_GREEN, - CLR_YELLOW, - CLR_BLUE, - CLR_PINK, - CLR_CYAN, - CLR_WHITE -}; - -#define IS_WARP4() (aulBuffer[0] == 20 && aulBuffer[1] >= 40) - -#ifndef min -#define min(a, b) (((a < b) ? a : b)) -#endif - -typedef struct _sighandler -{ - struct _sighandler *next; - ULONG message; - HWND window; - int id; - void *signalfunction; - void *data; - -} SignalHandler; - -SignalHandler *Root = NULL; - -typedef struct -{ - ULONG message; - char name[30]; - -} SignalList; - -/* List of signals and their equivilent OS/2 message */ -#define SIGNALMAX 16 - -SignalList SignalTranslate[SIGNALMAX] = { - { WM_SIZE, DW_SIGNAL_CONFIGURE }, - { WM_CHAR, DW_SIGNAL_KEY_PRESS }, - { WM_BUTTON1DOWN, DW_SIGNAL_BUTTON_PRESS }, - { WM_BUTTON1UP, DW_SIGNAL_BUTTON_RELEASE }, - { WM_MOUSEMOVE, DW_SIGNAL_MOTION_NOTIFY }, - { WM_CLOSE, DW_SIGNAL_DELETE }, - { WM_PAINT, DW_SIGNAL_EXPOSE }, - { WM_COMMAND, DW_SIGNAL_CLICKED }, - { CN_ENTER, DW_SIGNAL_ITEM_ENTER }, - { CN_CONTEXTMENU, DW_SIGNAL_ITEM_CONTEXT }, - { LN_SELECT, DW_SIGNAL_LIST_SELECT }, - { CN_EMPHASIS, DW_SIGNAL_ITEM_SELECT }, - { WM_SETFOCUS, DW_SIGNAL_SET_FOCUS }, - { SLN_SLIDERTRACK, DW_SIGNAL_VALUE_CHANGED }, - { BKN_PAGESELECTED,DW_SIGNAL_SWITCH_PAGE }, - { CN_EXPANDTREE, DW_SIGNAL_TREE_EXPAND } -}; - -/* This function adds a signal handler callback into the linked list. - */ -void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data) -{ - SignalHandler *new = malloc(sizeof(SignalHandler)); - - new->message = message; - new->window = window; - new->id = id; - new->signalfunction = signalfunction; - new->data = data; - new->next = NULL; - - if (!Root) - Root = new; - else - { - SignalHandler *prev = NULL, *tmp = Root; - while(tmp) - { - if(tmp->message == message && - tmp->window == window && - tmp->id == id && - tmp->signalfunction == signalfunction) - { - tmp->data = data; - free(new); - return; - } - prev = tmp; - tmp = tmp->next; - } - if(prev) - prev->next = new; - else - Root = new; - } -} - -/* Finds the message number for a given signal name */ -ULONG _findsigmessage(char *signame) -{ - int z; - - for(z=0;z<SIGNALMAX;z++) - { - if(stricmp(signame, SignalTranslate[z].name) == 0) - return SignalTranslate[z].message; - } - return 0L; -} - -typedef struct _CNRITEM -{ - MINIRECORDCORE rc; - HPOINTER hptrIcon; - PVOID user; - HTREEITEM parent; - -} CNRITEM, *PCNRITEM; - - -int _null_key(HWND window, int key, void *data) -{ - window = window; /* keep compiler happy */ - key = key; /* keep compiler happy */ - data = data; /* keep compiler happy */ - return TRUE; -} - -/* Find the desktop window handle */ -HWND _toplevel_window(HWND handle) -{ - HWND box, lastbox = WinQueryWindow(handle, QW_PARENT); - - /* Find the toplevel window */ - while((box = WinQueryWindow(lastbox, QW_PARENT)) != desktop && box > 0) - { - lastbox = box; - } - if(box > 0) - return lastbox; - return handle; -} - - -/* A "safe" WinSendMsg() that tries multiple times in case the - * queue is blocked for one reason or another. - */ -MRESULT _dw_send_msg(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2, int failure) -{ - MRESULT res; - int z = 0; - - while((int)(res = WinSendMsg(hwnd, msg, mp1, mp2)) == failure) - { - z++; - if(z > 5000000) - return (MRESULT)failure; - dw_main_sleep(1); - } - return res; -} - -/* Return the entryfield child of a window */ -HWND _find_entryfield(HWND handle) -{ - HENUM henum; - HWND child, entry = 0; - - henum = WinBeginEnumWindows(handle); - while((child = WinGetNextWindow(henum)) != NULLHANDLE) - { - char tmpbuf[100]; - - WinQueryClassName(child, 99, tmpbuf); - - if(strncmp(tmpbuf, "#6", 3)==0) /* Entryfield */ - { - entry = child; - break; - } - } - WinEndEnumWindows(henum); - return entry; -} - -/* This function changes the owner of buttons in to the - * dynamicwindows handle to fix a problem in notebooks. - */ -void _fix_button_owner(HWND handle, HWND dw) -{ - HENUM henum; - HWND child; - - henum = WinBeginEnumWindows(handle); - while((child = WinGetNextWindow(henum)) != NULLHANDLE) - { - char tmpbuf[100]; - - WinQueryClassName(child, 99, tmpbuf); - - if(strncmp(tmpbuf, "#3", 3)==0 && dw) /* Button */ - WinSetOwner(child, dw); - else if(strncmp(tmpbuf, "dynamicwindows", 14) == 0) - dw = child; - - _fix_button_owner(child, dw); - } - WinEndEnumWindows(henum); - return; -} - -/* Free bitmap data associated with a window */ -void _free_bitmap(HWND handle) -{ - HBITMAP hbm = (HBITMAP)dw_window_get_data(handle, "_dw_bitmap"); - HPS hps = (HPS)dw_window_get_data(handle, "_dw_hps"); - HDC hdc = (HDC)dw_window_get_data(handle, "_dw_hdc"); - HPIXMAP pixmap = (HPIXMAP)dw_window_get_data(handle, "_dw_hpixmap"); - HPIXMAP disable = (HPIXMAP)dw_window_get_data(handle, "_dw_hpixmap_disabled"); - - if(pixmap) - dw_pixmap_destroy(pixmap); - - if(disable) - dw_pixmap_destroy(disable); - - if(hps) - { - GpiSetBitmap(hps, NULLHANDLE); - GpiAssociate(hps, NULLHANDLE); - GpiDestroyPS(hps); - } - - if(hdc) - DevCloseDC(hdc); - - if(hbm) - GpiDeleteBitmap(hbm); -} - -/* This function removes and handlers on windows and frees - * the user memory allocated to it. - */ -void _free_window_memory(HWND handle) -{ - HENUM henum; - HWND child; - void *ptr = (void *)WinQueryWindowPtr(handle, QWP_USER); - - dw_signal_disconnect_by_window(handle); - - if((child = WinWindowFromID(handle, FID_MENU)) != NULLHANDLE) - _free_menu_data(child); - - if((child = WinWindowFromID(handle, FID_CLIENT)) != NULLHANDLE) - { - Box *box = (Box *)WinQueryWindowPtr(child, QWP_USER); - - if(box) - { - if(box->count && box->items) - free(box->items); - - WinSetWindowPtr(child, QWP_USER, 0); - free(box); - } - } - - if(ptr) - { - WindowData *wd = (WindowData *)ptr; - char tmpbuf[100]; - - /* If this window has an associate bitmap destroy it. */ - _free_bitmap(handle); - - WinQueryClassName(handle, 99, tmpbuf); - - if(strncmp(tmpbuf, "#1", 3)==0) - { - Box *box = (Box *)ptr; - - if(box->count && box->items) - free(box->items); - } - else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0) - { - void *data = dw_window_get_data(handle, "_dw_percent"); - - if(data) - free(data); - } - else if(strncmp(tmpbuf, "#37", 4)==0) - { - dw_container_clear(handle, FALSE); - if(wd && dw_window_get_data(handle, "_dw_container")) - { - void *oldflags = wd->data; - - wd->data = NULL; - free(oldflags); - } - } - - if(wd->oldproc) - WinSubclassWindow(handle, wd->oldproc); - - dw_window_set_data(handle, NULL, NULL); - WinSetWindowPtr(handle, QWP_USER, 0); - free(ptr); - } - - henum = WinBeginEnumWindows(handle); - while((child = WinGetNextWindow(henum)) != NULLHANDLE) - _free_window_memory(child); - - WinEndEnumWindows(henum); - return; -} - -void _free_menu_data(HWND menu) -{ - int i, count = (int)WinSendMsg(menu, MM_QUERYITEMCOUNT, 0, 0); - - dw_signal_disconnect_by_name(menu, DW_SIGNAL_CLICKED); - _free_window_memory(menu); - - for(i=0;i<count;i++) - { - SHORT menuid = (SHORT)WinSendMsg(menu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(i), 0); - MENUITEM mi; - - if(WinSendMsg(menu, MM_QUERYITEM, MPFROMSHORT(menuid), MPFROMP(&mi)) - && mi.hwndSubMenu) - _free_menu_data(mi.hwndSubMenu); - } -} - -/* This function returns 1 if the window (widget) handle - * passed to it is a valid window that can gain input focus. - */ -int _validate_focus(HWND handle) -{ - char tmpbuf[100]; - - if(!handle) - return 0; - - if(!WinIsWindowEnabled(handle) || dw_window_get_data(handle, "_dw_disabled")) - return 0; - - WinQueryClassName(handle, 99, tmpbuf); - - /* These are the window classes which can - * obtain input focus. - */ - if(strncmp(tmpbuf, "#2", 3)==0 || /* Combobox */ - strncmp(tmpbuf, "#3", 3)==0 || /* Button */ - strncmp(tmpbuf, "#6", 3)==0 || /* Entryfield */ - strncmp(tmpbuf, "#7", 3)==0 || /* List box */ - strncmp(tmpbuf, "#10", 4)==0 || /* MLE */ - strncmp(tmpbuf, "#32", 4)==0 || /* Spinbutton */ - strncmp(tmpbuf, "#37", 4)==0 || /* Container */ - strncmp(tmpbuf, "#38", 4)== 0) /* Slider */ - return 1; - return 0; -} - -int _focus_check_box(Box *box, HWND handle, int start, HWND defaultitem) -{ - int z, n; - 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(n=0;n<box->count;n++) - { - /* Vertical boxes are inverted on OS/2 */ - if(box->type == DW_VERT) - z = n; - else - z = box->count - n - 1; - - 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)) - 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] = ""; - - WinQueryClassName(box->items[z].hwnd, 99, tmpbuf); - 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"); - - if(mybox) - { - Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER); - - if(splitbox && _focus_check_box(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_query(box->items[z].hwnd), 0); - - if(page) - { - notebox = (Box *)WinQueryWindowPtr(page, QWP_USER); - - if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - } - } - } - } - return 0; -} - -int _focus_check_box_back(Box *box, HWND handle, int start, HWND defaultitem) -{ - int z, n; - 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(n=0;n<box->count;n++) - { - /* Vertical boxes are inverted on OS/2 */ - if(box->type == DW_VERT) - z = box->count - n - 1; - else - z = n; - - 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)) - 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] = ""; - - WinQueryClassName(box->items[z].hwnd, 99, 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_query(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; - } - } - } - } - } - return 0; -} - -/* This function finds the first widget in the - * layout and moves the current focus to it. - */ -int _initial_focus(HWND handle) -{ - Box *thisbox = NULL; - HWND box; - - box = WinWindowFromID(handle, FID_CLIENT); - if(box) - thisbox = WinQueryWindowPtr(box, QWP_USER); - else - return 1; - - if(thisbox) - _focus_check_box(thisbox, handle, 3, 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) -{ - 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(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); - } -} - -/* This function will recursively search a box and add up the total height of it */ -void _count_size(HWND box, int type, int *xsize, int *xorigsize) -{ - int size = 0, origsize = 0, z; - Box *tmp = WinQueryWindowPtr(box, QWP_USER); - - if(!tmp) - { - *xsize = *xorigsize = 0; - return; - } - - if(type == tmp->type) - { - /* If the box is going in the direction we want, then we - * return the entire sum of the items. - */ - for(z=0;z<tmp->count;z++) - { - if(tmp->items[z].type == TYPEBOX) - { - int s, os; - - _count_size(tmp->items[z].hwnd, type, &s, &os); - size += s; - origsize += os; - } - else - { - size += (type == DW_HORZ ? tmp->items[z].width : tmp->items[z].height); - origsize += (type == DW_HORZ ? tmp->items[z].origwidth : tmp->items[z].origheight); - } - } - } - else - { - /* If the box is not going in the direction we want, then we only - * want to return the maximum value. - */ - int tmpsize = 0, tmporigsize = 0; - - for(z=0;z<tmp->count;z++) - { - if(tmp->items[z].type == TYPEBOX) - _count_size(tmp->items[z].hwnd, type, &tmpsize, &tmporigsize); - else - { - tmpsize = (type == DW_HORZ ? tmp->items[z].width : tmp->items[z].height); - tmporigsize = (type == DW_HORZ ? tmp->items[z].origwidth : tmp->items[z].origheight); - } - - if(tmpsize > size) - size = tmpsize; - } - } - - *xsize = size; - *xorigsize = origsize; -} - - -/* Function: TrackRectangle - * Abstract: Tracks given rectangle. - * - * If rclBounds is NULL, then track rectangle on entire desktop. - * rclTrack is in window coorditates and will be mapped to - * desktop. - */ - -BOOL _TrackRectangle(HWND hwndBase, RECTL* rclTrack, RECTL* rclBounds) -{ - TRACKINFO track; - APIRET rc; - - track.cxBorder = 1; - track.cyBorder = 1; - track.cxGrid = 1; - track.cyGrid = 1; - track.cxKeyboard = 8; - track.cyKeyboard = 8; - - if(!rclTrack) - return FALSE; - - if(rclBounds) - { - track.rclBoundary = *rclBounds; - } - else - { - track.rclBoundary.yTop = - track.rclBoundary.xRight = 3000; - track.rclBoundary.yBottom = - track.rclBoundary.xLeft = -3000; - } - - track.rclTrack = *rclTrack; - - WinMapWindowPoints(hwndBase, - HWND_DESKTOP, - (PPOINTL)&track.rclTrack, - 2); - - track.ptlMinTrackSize.x = track.rclTrack.xRight - - track.rclTrack.xLeft; - track.ptlMinTrackSize.y = track.rclTrack.yTop - - track.rclTrack.yBottom; - track.ptlMaxTrackSize.x = track.rclTrack.xRight - - track.rclTrack.xLeft; - track.ptlMaxTrackSize.y = track.rclTrack.yTop - - track.rclTrack.yBottom; - - track.fs = TF_MOVE | TF_ALLINBOUNDARY; - - rc = WinTrackRect(HWND_DESKTOP, 0, &track); - - if(rc) - *rclTrack = track.rclTrack; - - return rc; -} - -void _check_resize_notebook(HWND hwnd) -{ - char tmpbuf[100]; - - WinQueryClassName(hwnd, 99, tmpbuf); - - /* If we have a notebook we resize the page again. */ - if(strncmp(tmpbuf, "#40", 4)==0) - { - unsigned long x, y, width, height; - ULONG page = (ULONG)WinSendMsg(hwnd, BKM_QUERYPAGEID, 0, MPFROM2SHORT(BKA_FIRST, BKA_MAJOR)); - - while(page) - { - HWND pagehwnd = (HWND)WinSendMsg(hwnd, BKM_QUERYPAGEWINDOWHWND, MPFROMLONG(page), 0); - RECTL rc; - - Box *pagebox = (Box *)WinQueryWindowPtr(pagehwnd, QWP_USER); - if(pagebox) - { - dw_window_get_pos_size(hwnd, &x, &y, &width, &height); - - rc.xLeft = x; - rc.yBottom = y; - rc.xRight = x + width; - rc.yTop = y + height; - - WinSendMsg(hwnd, BKM_CALCPAGERECT, (MPARAM)&rc, (MPARAM)TRUE); - - _do_resize(pagebox, rc.xRight - rc.xLeft, rc.yTop - rc.yBottom); - } - page = (ULONG)WinSendMsg(hwnd, BKM_QUERYPAGEID, (MPARAM)page, MPFROM2SHORT(BKA_NEXT, BKA_MAJOR)); - } - - } -} - -/* Return the OS/2 color from the DW color */ -unsigned long _internal_color(unsigned long color) -{ - if(color < 16) - return _colors[color]; - return color; -} - -/* This function calculates how much space the widgets and boxes require - * and does expansion as necessary. - */ -int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy, - int pass, int *usedpadx, int *usedpady) -{ - int z, currentx = 0, currenty = 0; - int uymax = 0, uxmax = 0; - int upymax = 0, upxmax = 0; - /* Used for the SIZEEXPAND */ - int nux = *usedx, nuy = *usedy; - int nupx = *usedpadx, nupy = *usedpady; - - (*usedx) += (thisbox->pad * 2); - (*usedy) += (thisbox->pad * 2); - - if(thisbox->grouphwnd) - { - char *text = dw_window_get_text(thisbox->grouphwnd); - - thisbox->grouppady = 0; - - if(text) - { - dw_font_text_extents(thisbox->grouphwnd, 0, text, NULL, &thisbox->grouppady); - dw_free(text); - } - - if(thisbox->grouppady) - thisbox->grouppady += 3; - else - thisbox->grouppady = 6; - - thisbox->grouppadx = 6; - - (*usedx) += thisbox->grouppadx; - (*usedpadx) += thisbox->grouppadx; - (*usedy) += thisbox->grouppady; - (*usedpady) += thisbox->grouppady; - } - - for(z=0;z<thisbox->count;z++) - { - if(thisbox->items[z].type == TYPEBOX) - { - int initialx, initialy; - Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER); - - initialx = x - (*usedx); - initialy = y - (*usedy); - - if(tmp) - { - int newx, newy; - int nux = *usedx, nuy = *usedy; - int upx = *usedpadx + (tmp->pad*2), upy = *usedpady + (tmp->pad*2); - - /* On the second pass we know how big the box needs to be and how - * much space we have, so we can calculate a ratio for the new box. - */ - if(pass == 2) - { - int deep = *depth + 1; - - _resize_box(tmp, &deep, x, y, &nux, &nuy, 1, &upx, &upy); - - tmp->upx = upx - *usedpadx; - tmp->upy = upy - *usedpady; - - newx = x - nux; - newy = y - nuy; - - tmp->width = thisbox->items[z].width = initialx - newx; - tmp->height = thisbox->items[z].height = initialy - newy; - - tmp->parentxratio = thisbox->xratio; - tmp->parentyratio = thisbox->yratio; - - tmp->parentpad = tmp->pad; - - /* Just in case */ - tmp->xratio = thisbox->xratio; - tmp->yratio = thisbox->yratio; - - if(thisbox->type == DW_VERT) - { - int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppady; - - if((thisbox->items[z].width - tmppad)!=0) - tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmppad))/((float)(thisbox->items[z].width-tmppad)); - } - else - { - if((thisbox->items[z].width-tmp->upx)!=0) - tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx)); - } - if(thisbox->type == DW_HORZ) - { - int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppadx; - - if((thisbox->items[z].height-tmppad)!=0) - tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmppad))/((float)(thisbox->items[z].height-tmppad)); - } - else - { - if((thisbox->items[z].height-tmp->upy)!=0) - tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy)); - } - - nux = *usedx; nuy = *usedy; - upx = *usedpadx + (tmp->pad*2); upy = *usedpady + (tmp->pad*2); - } - - (*depth)++; - - _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy); - - (*depth)--; - - newx = x - nux; - newy = y - nuy; - - tmp->minwidth = thisbox->items[z].width = initialx - newx; - tmp->minheight = thisbox->items[z].height = initialy - newy; - } - } - - if(pass > 1 && *depth > 0) - { - if(thisbox->type == DW_VERT) - { - int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppadx; - - if((thisbox->minwidth-tmppad) == 0) - thisbox->items[z].xratio = 1.0; - else - thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-tmppad))/((float)(thisbox->minwidth-tmppad)); - } - else - { - if(thisbox->minwidth-thisbox->upx == 0) - thisbox->items[z].xratio = 1.0; - else - thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx)); - } - - if(thisbox->type == DW_HORZ) - { - int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppady; - - if((thisbox->minheight-tmppad) == 0) - thisbox->items[z].yratio = 1.0; - else - thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-tmppad))/((float)(thisbox->minheight-tmppad)); - } - else - { - if(thisbox->minheight-thisbox->upy == 0) - thisbox->items[z].yratio = 1.0; - else - thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy)); - } - - if(thisbox->items[z].type == TYPEBOX) - { - Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER); - - if(tmp) - { - tmp->parentxratio = thisbox->items[z].xratio; - tmp->parentyratio = thisbox->items[z].yratio; - } - } - } - else - { - thisbox->items[z].xratio = thisbox->xratio; - thisbox->items[z].yratio = thisbox->yratio; - } - - if(thisbox->type == DW_VERT) - { - int itemwidth = thisbox->items[z].width + (thisbox->items[z].pad*2); - - if(itemwidth > uxmax) - uxmax = itemwidth; - if(thisbox->items[z].hsize != SIZEEXPAND) - { - if(itemwidth > upxmax) - upxmax = itemwidth; - } - else - { - if(thisbox->items[z].pad*2 > upxmax) - upxmax = thisbox->items[z].pad*2; - } - } - else - { - if(thisbox->items[z].width == -1) - { - /* figure out how much space this item requires */ - /* thisbox->items[z].width = */ - } - else - { - (*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2); - if(thisbox->items[z].hsize != SIZEEXPAND) - (*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width; - else - (*usedpadx) += thisbox->items[z].pad*2; - } - } - if(thisbox->type == DW_HORZ) - { - int itemheight = thisbox->items[z].height + (thisbox->items[z].pad*2); - - if(itemheight > uymax) - uymax = itemheight; - if(thisbox->items[z].vsize != SIZEEXPAND) - { - if(itemheight > upymax) - upymax = itemheight; - } - else - { - if(thisbox->items[z].pad*2 > upymax) - upymax = thisbox->items[z].pad*2; - } - } - else - { - if(thisbox->items[z].height == -1) - { - /* figure out how much space this item requires */ - /* thisbox->items[z].height = */ - } - else - { - (*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2); - if(thisbox->items[z].vsize != SIZEEXPAND) - (*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height; - else - (*usedpady) += thisbox->items[z].pad*2; - } - } - } - - (*usedx) += uxmax; - (*usedy) += uymax; - (*usedpadx) += upxmax; - (*usedpady) += upymax; - - currentx += thisbox->pad; - currenty += thisbox->pad; - - if(thisbox->grouphwnd) - { - currentx += 3; - currenty += 3; - } - - /* The second pass is for expansion and actual placement. */ - if(pass > 1) - { - /* Any SIZEEXPAND items should be set to uxmax/uymax */ - for(z=0;z<thisbox->count;z++) - { - if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == DW_VERT) - thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2); - if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == DW_HORZ) - thisbox->items[z].height = uymax-(thisbox->items[z].pad*2); - /* Run this code segment again to finalize the sized after setting uxmax/uymax values. */ - if(thisbox->items[z].type == TYPEBOX) - { - Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER); - - if(tmp) - { - if(*depth > 0) - { - float calcval; - - if(thisbox->type == DW_VERT) - { - calcval = (float)(tmp->minwidth-((thisbox->items[z].pad*2)+(thisbox->pad*2))); - if(calcval == 0.0) - tmp->xratio = thisbox->xratio; - else - tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval; - tmp->width = thisbox->items[z].width; - } - if(thisbox->type == DW_HORZ) - { - calcval = (float)(tmp->minheight-((thisbox->items[z].pad*2)+(thisbox->pad*2))); - if(calcval == 0.0) - tmp->yratio = thisbox->yratio; - else - tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval; - tmp->height = thisbox->items[z].height; - } - } - - (*depth)++; - - _resize_box(tmp, depth, x, y, &nux, &nuy, 3, &nupx, &nupy); - - (*depth)--; - - } - } - } - - for(z=0;z<(thisbox->count);z++) - { - int height = thisbox->items[z].height; - int width = thisbox->items[z].width; - int pad = thisbox->items[z].pad; - HWND handle = thisbox->items[z].hwnd; - int vectorx, vectory; - - /* When upxmax != pad*2 then ratios are incorrect. */ - vectorx = (int)((width*thisbox->items[z].xratio)-width); - vectory = (int)((height*thisbox->items[z].yratio)-height); - - if(width > 0 && height > 0) - { - char tmpbuf[100]; - /* This is a hack to fix rounding of the sizing */ - if(*depth == 0) - { - vectorx++; - vectory++; - } - - /* If this item isn't going to expand... reset the vectors to 0 */ - if(thisbox->items[z].vsize != SIZEEXPAND) - vectory = 0; - if(thisbox->items[z].hsize != SIZEEXPAND) - vectorx = 0; - - WinQueryClassName(handle, 99, tmpbuf); - - if(strncmp(tmpbuf, "#2", 3)==0) - { - HWND frame = (HWND)dw_window_get_data(handle, "_dw_combo_box"); - /* Make the combobox big enough to drop down. :) */ - WinSetWindowPos(handle, HWND_TOP, 0, -100, - width + vectorx, (height + vectory) + 100, SWP_MOVE | SWP_SIZE | SWP_ZORDER); - WinSetWindowPos(frame, HWND_TOP, currentx + pad, currenty + pad, - width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER); - } - else if(strncmp(tmpbuf, "#6", 3)==0) - { - /* Entryfields on OS/2 have a thick border that isn't on Windows and GTK */ - WinSetWindowPos(handle, HWND_TOP, (currentx + pad) + 3, (currenty + pad) + 3, - (width + vectorx) - 6, (height + vectory) - 6, SWP_MOVE | SWP_SIZE | SWP_ZORDER); - } - else if(strncmp(tmpbuf, "#40", 5)==0) - { - WinSetWindowPos(handle, HWND_TOP, currentx + pad, currenty + pad, - width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER); - _check_resize_notebook(handle); - } - else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0) - { - /* 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 cx = width + vectorx; - int cy = height + vectory; - - WinSetWindowPos(handle, HWND_TOP, currentx + pad, currenty + pad, - cx, cy, SWP_MOVE | SWP_SIZE | SWP_ZORDER); - - if(cx > 0 && cy > 0 && percent) - _handle_splitbar_resize(handle, *percent, type, cx, cy); - } - else - { - WinSetWindowPos(handle, HWND_TOP, currentx + pad, currenty + pad, - width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER); - if(thisbox->items[z].type == TYPEBOX) - { - Box *boxinfo = WinQueryWindowPtr(handle, QWP_USER); - - if(boxinfo && boxinfo->grouphwnd) - WinSetWindowPos(boxinfo->grouphwnd, HWND_TOP, 0, 0, - width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE); - - } - - } - - if(thisbox->type == DW_HORZ) - currentx += width + vectorx + (pad * 2); - if(thisbox->type == DW_VERT) - currenty += height + vectory + (pad * 2); - } - } - } - return 0; -} - -void _do_resize(Box *thisbox, int x, int y) -{ - if(x != 0 && y != 0) - { - if(thisbox) - { - int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0; - - _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady); - - if(usedx-usedpadx == 0 || usedy-usedpady == 0) - return; - - thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx)); - thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady)); - - usedx = usedy = usedpadx = usedpady = depth = 0; - - _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady); - } - } -} - -/* This procedure handles WM_QUERYTRACKINFO requests from the frame */ -MRESULT EXPENTRY _sizeproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER); - Box *thisbox = NULL; - HWND box; - - box = WinWindowFromID(hWnd, FID_CLIENT); - if(box) - thisbox = WinQueryWindowPtr(box, QWP_USER); - - if(thisbox && !thisbox->titlebar) - { - switch(msg) - { - case WM_QUERYTRACKINFO: - { - if(blah && *blah) - { - PTRACKINFO ptInfo; - int res; - PFNWP myfunc = *blah; - res = (int)myfunc(hWnd, msg, mp1, mp2); - - ptInfo = (PTRACKINFO)(mp2); - - ptInfo->ptlMinTrackSize.y = 8; - ptInfo->ptlMinTrackSize.x = 8; - - return (MRESULT)res; - } - } - } - } - - if(blah && *blah) - { - PFNWP myfunc = *blah; - return myfunc(hWnd, msg, mp1, mp2); - } - - return WinDefWindowProc(hWnd, msg, mp1, mp2); -} - -void _Top(HPS hpsPaint, RECTL rclPaint) -{ - POINTL ptl1, ptl2; - - ptl1.x = rclPaint.xLeft; - ptl2.y = ptl1.y = rclPaint.yTop - 1; - ptl2.x = rclPaint.xRight - 1; - GpiMove(hpsPaint, &ptl1); - GpiLine(hpsPaint, &ptl2); -} - -/* Left hits the bottom */ -void _Left(HPS hpsPaint, RECTL rclPaint) -{ - POINTL ptl1, ptl2; - - ptl2.x = ptl1.x = rclPaint.xLeft; - ptl1.y = rclPaint.yTop - 1; - ptl2.y = rclPaint.yBottom; - GpiMove(hpsPaint, &ptl1); - GpiLine(hpsPaint, &ptl2); -} - -void _Bottom(HPS hpsPaint, RECTL rclPaint) -{ - POINTL ptl1, ptl2; - - ptl1.x = rclPaint.xRight - 1; - ptl1.y = ptl2.y = rclPaint.yBottom; - ptl2.x = rclPaint.xLeft; - GpiMove(hpsPaint, &ptl1); - GpiLine(hpsPaint, &ptl2); -} - -/* Right hits the top */ -void _Right(HPS hpsPaint, RECTL rclPaint) -{ - POINTL ptl1, ptl2; - - ptl2.x = ptl1.x = rclPaint.xRight - 1; - ptl1.y = rclPaint.yBottom + 1; - ptl2.y = rclPaint.yTop - 1; - GpiMove(hpsPaint, &ptl1); - GpiLine(hpsPaint, &ptl2); -} - -/* This procedure handles drawing of a status border */ -MRESULT EXPENTRY _statusproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER); - - if(blah && *blah) - { - PFNWP myfunc = *blah; - - switch(msg) - { - case WM_PAINT: - { - HPS hpsPaint; - RECTL rclPaint; - char buf[1024]; - - hpsPaint = WinBeginPaint(hWnd, 0, 0); - WinQueryWindowRect(hWnd, &rclPaint); - WinFillRect(hpsPaint, &rclPaint, CLR_PALEGRAY); - - GpiSetColor(hpsPaint, CLR_DARKGRAY); - _Top(hpsPaint, rclPaint); - _Left(hpsPaint, rclPaint); - - GpiSetColor(hpsPaint, CLR_WHITE); - _Right(hpsPaint, rclPaint); - _Bottom(hpsPaint, rclPaint); - - WinQueryWindowText(hWnd, 1024, buf); - rclPaint.xLeft += 3; - rclPaint.xRight--; - rclPaint.yTop--; - rclPaint.yBottom++; - - GpiSetColor(hpsPaint, CLR_BLACK); - WinDrawText(hpsPaint, -1, buf, &rclPaint, DT_TEXTATTRS, DT_TEXTATTRS, DT_VCENTER | DT_LEFT | DT_TEXTATTRS); - WinEndPaint(hpsPaint); - - return (MRESULT)TRUE; - } - } - return myfunc(hWnd, msg, mp1, mp2); - } - - return WinDefWindowProc(hWnd, msg, mp1, mp2); -} - -void _click_default(HWND handle) -{ - char tmpbuf[100]; - - WinQueryClassName(handle, 99, tmpbuf); - - /* These are the window classes which can - * obtain input focus. - */ - if(strncmp(tmpbuf, "#3", 3)==0) - { - /* Generate click on default item */ - SignalHandler *tmp = Root; - - /* Find any callbacks for this function */ - while(tmp) - { - if(tmp->message == WM_COMMAND) - { - int (*clickfunc)(HWND, void *) = (int (*)(HWND, void *))tmp->signalfunction; - - /* Make sure it's the right window, and the right ID */ - if(tmp->window == handle) - { - clickfunc(tmp->window, tmp->data); - tmp = NULL; - } - } - if(tmp) - tmp= tmp->next; - } - } - else - WinSetFocus(HWND_DESKTOP, handle); -} - -#define ENTRY_CUT 1001 -#define ENTRY_COPY 1002 -#define ENTRY_PASTE 1003 -#define ENTRY_UNDO 1004 -#define ENTRY_SALL 1005 - -/* Originally just intended for entryfields, it now serves as a generic - * procedure for handling TAB presses to change input focus on controls. - */ -MRESULT EXPENTRY _entryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER); - PFNWP oldproc = 0; - char tmpbuf[100]; - - if(blah) - oldproc = blah->oldproc; - - WinQueryClassName(hWnd, 99, tmpbuf); - - /* These are the window classes which should get a menu */ - if(strncmp(tmpbuf, "#2", 3)==0 || /* Combobox */ - strncmp(tmpbuf, "#6", 3)==0 || /* Entryfield */ - strncmp(tmpbuf, "#10", 4)==0 || /* MLE */ - strncmp(tmpbuf, "#32", 4)==0) /* Spinbutton */ - { - switch(msg) - { - case WM_CONTEXTMENU: - { - HMENUI hwndMenu = dw_menu_new(0L); - long x, y; - - if(strncmp(tmpbuf, "#10", 4)==0 && !WinSendMsg(hWnd, MLM_QUERYREADONLY, 0, 0)) - { - dw_menu_append_item(hwndMenu, "Undo", ENTRY_UNDO, 0L, TRUE, FALSE, 0L); - dw_menu_append_item(hwndMenu, "", 0L, 0L, TRUE, FALSE, 0L); - } - dw_menu_append_item(hwndMenu, "Copy", ENTRY_COPY, 0L, TRUE, FALSE, 0L); - if((strncmp(tmpbuf, "#10", 4)!=0 && !dw_window_get_data(hWnd, "_dw_disabled")) || (strncmp(tmpbuf, "#10", 4)==0 && !WinSendMsg(hWnd, MLM_QUERYREADONLY, 0, 0))) - { - dw_menu_append_item(hwndMenu, "Cut", ENTRY_CUT, 0L, TRUE, FALSE, 0L); - dw_menu_append_item(hwndMenu, "Paste", ENTRY_PASTE, 0L, TRUE, FALSE, 0L); - } - dw_menu_append_item(hwndMenu, "", 0L, 0L, TRUE, FALSE, 0L); - dw_menu_append_item(hwndMenu, "Select All", ENTRY_SALL, 0L, TRUE, FALSE, 0L); - - WinSetFocus(HWND_DESKTOP, hWnd); - dw_pointer_query_pos(&x, &y); - dw_menu_popup(&hwndMenu, hWnd, x, y); - } - break; - case WM_COMMAND: - { - ULONG command = COMMANDMSG(&msg)->cmd; - - /* MLE */ - if(strncmp(tmpbuf, "#10", 4)==0) - { - switch(command) - { - case ENTRY_CUT: - return WinSendMsg(hWnd, MLM_CUT, 0, 0); - case ENTRY_COPY: - return WinSendMsg(hWnd, MLM_COPY, 0, 0); - case ENTRY_PASTE: - return WinSendMsg(hWnd, MLM_PASTE, 0, 0); - case ENTRY_UNDO: - return WinSendMsg(hWnd, MLM_UNDO, 0, 0); - case ENTRY_SALL: - { - ULONG len = (ULONG)WinSendMsg(hWnd, MLM_QUERYTEXTLENGTH, 0, 0); - return WinSendMsg(hWnd, MLM_SETSEL, 0, (MPARAM)len); - } - } - } - else /* Other */ - { - HWND handle = hWnd; - - /* Get the entryfield handle from multi window controls */ - if(strncmp(tmpbuf, "#2", 3)==0) - handle = WinWindowFromID(hWnd, 667); - - if(handle) - { - switch(command) - { - case ENTRY_CUT: - return WinSendMsg(handle, EM_CUT, 0, 0); - case ENTRY_COPY: - return WinSendMsg(handle, EM_COPY, 0, 0); - case ENTRY_PASTE: - return WinSendMsg(handle, EM_PASTE, 0, 0); - case ENTRY_SALL: - { - LONG len = WinQueryWindowTextLength(hWnd); - return WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT(0, (SHORT)len), 0); - } - } - } - } - } - break; - } - } - - switch(msg) - { - case WM_BUTTON1DOWN: - case WM_BUTTON2DOWN: - case WM_BUTTON3DOWN: - { - if(strncmp(tmpbuf, "#32", 4)==0) - _run_event(hWnd, WM_SETFOCUS, (MPARAM)FALSE, (MPARAM)TRUE); - } - break; - case WM_CONTROL: - { - if(strncmp(tmpbuf, "#38", 4)==0) - _run_event(hWnd, msg, mp1, mp2); - } - break; - case WM_SETFOCUS: - _run_event(hWnd, msg, mp1, mp2); - break; - case WM_CHAR: - if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE) - return (MRESULT)TRUE; - if(SHORT1FROMMP(mp2) == '\t') - { - if(CHARMSG(&msg)->fs & KC_SHIFT) - _shift_focus_back(hWnd); - else - _shift_focus(hWnd); - return FALSE; - } - else if(SHORT1FROMMP(mp2) == '\r' && blah && blah->clickdefault) - _click_default(blah->clickdefault); - /* When you hit escape we get this value and the - * window hangs for reasons unknown. (in an MLE) - */ - else if(SHORT1FROMMP(mp2) == 283) - return (MRESULT)TRUE; - - break; - case WM_SIZE: - { - /* If it's a slider... make sure it shows the correct value */ - if(strncmp(tmpbuf, "#38", 4)==0) - WinPostMsg(hWnd, WM_USER+7, 0, 0); - } - break; - case WM_USER+7: - { - int pos = (int)dw_window_get_data(hWnd, "_dw_slider_value"); - WinSendMsg(hWnd, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), (MPARAM)pos); - } - break; - } - - if(oldproc) - return oldproc(hWnd, msg, mp1, mp2); - - return WinDefWindowProc(hWnd, msg, mp1, mp2); -} - -/* Deal with combobox specifics and enhancements */ -MRESULT EXPENTRY _comboentryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER); - - switch(msg) - { - case WM_CONTEXTMENU: - case WM_COMMAND: - return _entryproc(hWnd, msg, mp1, mp2); - case WM_SETFOCUS: - _run_event(hWnd, msg, mp1, mp2); - break; - case WM_CHAR: - if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE) - return (MRESULT)TRUE; - /* A Similar problem to the MLE, if ESC just return */ - if(SHORT1FROMMP(mp2) == 283) - return (MRESULT)TRUE; - break; - } - - if(blah && blah->oldproc) - return blah->oldproc(hWnd, msg, mp1, mp2); - - return WinDefWindowProc(hWnd, msg, mp1, mp2); -} - -/* Enhance the standard OS/2 MLE control */ -MRESULT EXPENTRY _mleproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - switch(msg) - { - case WM_VSCROLL: - if(SHORT2FROMMP(mp2) == SB_SLIDERTRACK) - { - USHORT pos = SHORT1FROMMP(mp2); - - WinSendMsg(hWnd, msg, mp1, MPFROM2SHORT(pos, SB_SLIDERPOSITION)); - } - break; - } - return _entryproc(hWnd, msg, mp1, mp2); -} - -/* Handle special messages for the spinbutton's entryfield */ -MRESULT EXPENTRY _spinentryproc(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_CONTEXTMENU: - case WM_COMMAND: - return _entryproc(hWnd, msg, mp1, mp2); - } - - if(oldproc) - return oldproc(hWnd, msg, mp1, mp2); - - return WinDefWindowProc(hWnd, msg, mp1, mp2); -} - -int _dw_int_pos(HWND hwnd) -{ - int pos = (int)dw_window_get_data(hwnd, "_dw_percent_value"); - int range = dw_percent_query_range(hwnd); - float fpos = (float)pos; - float frange = (float)range; - float fnew = (fpos/1000.0)*frange; - return (int)fnew; -} - -void _dw_int_set(HWND hwnd, int pos) -{ - int inew, range = dw_percent_query_range(hwnd); - if(range) - { - float fpos = (float)pos; - float frange = (float)range; - float fnew = (fpos/frange)*1000.0; - inew = (int)fnew; - dw_window_set_data(hwnd, "_dw_percent_value", (void *)inew); - } -} - -/* Handle size changes in the percent class */ -MRESULT EXPENTRY _percentproc(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_SIZE: - WinPostMsg(hWnd, WM_USER+7, 0, 0); - break; - case WM_USER+7: - WinSendMsg(hWnd, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), (MPARAM)_dw_int_pos(hWnd)); - break; - } - - if(oldproc) - return oldproc(hWnd, msg, mp1, mp2); - - return WinDefWindowProc(hWnd, msg, mp1, mp2); -} - -/* Handle correct painting of a combobox with the WS_CLIPCHILDREN - * flag enabled, and also handle TABs to switch input focus. - */ -MRESULT EXPENTRY _comboproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - WindowData *blah = WinQueryWindowPtr(hWnd, QWP_USER); - PFNWP oldproc = 0; - - if(blah) - oldproc = blah->oldproc; - - switch(msg) - { - case WM_CHAR: - if(SHORT1FROMMP(mp2) == '\t') - { - if(CHARMSG(&msg)->fs & KC_SHIFT) - _shift_focus_back(hWnd); - else - _shift_focus(hWnd); - return FALSE; - } - else if(SHORT1FROMMP(mp2) == '\r' && blah && blah->clickdefault) - _click_default(blah->clickdefault); - break; - case WM_BUTTON1DBLCLK: - case WM_BUTTON2DBLCLK: - case WM_BUTTON3DBLCLK: - if(dw_window_get_data(hWnd, "_dw_disabled")) - return (MRESULT)TRUE; - break; - case WM_BUTTON1DOWN: - case WM_BUTTON2DOWN: - case WM_BUTTON3DOWN: - if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE) - return (MRESULT)TRUE; - _run_event(hWnd, WM_SETFOCUS, (MPARAM)FALSE, (MPARAM)TRUE); - break; - case WM_SETFOCUS: - _run_event(hWnd, msg, mp1, mp2); - break; - case WM_PAINT: - { - HWND entry, frame = (HWND)dw_window_get_data(hWnd, "_dw_combo_box"), parent = WinQueryWindow(frame, QW_PARENT); - HPS hpsPaint; - POINTL ptl; - unsigned long width, height, thumbheight = 0; - ULONG color; - - if((entry = (HWND)dw_window_get_data(hWnd, "_dw_comboentry")) != NULLHANDLE) - dw_window_get_pos_size(entry, 0, 0, 0, &thumbheight); - - if(!thumbheight) - thumbheight = WinQuerySysValue(HWND_DESKTOP, SV_CYVSCROLLARROW); - - /* Add 6 because it has a thick border like the entryfield */ - thumbheight += 6; - - color = (ULONG)dw_window_get_data(parent, "_dw_fore"); - dw_window_get_pos_size(hWnd, 0, 0, &width, &height); - - if(height > thumbheight) - { - hpsPaint = WinGetPS(hWnd); - if(color) - GpiSetColor(hpsPaint, _internal_color(color-1)); - else - GpiSetColor(hpsPaint, CLR_PALEGRAY); - - ptl.x = ptl.y = 0; - GpiMove(hpsPaint, &ptl); - - ptl.x = width; - ptl.y = height - thumbheight; - GpiBox(hpsPaint, DRO_FILL, &ptl, 0, 0); - - WinReleasePS(hpsPaint); - } - } - break; - } - if(oldproc) - return oldproc(hWnd, msg, mp1, mp2); - - return WinDefWindowProc(hWnd, msg, mp1, mp2); -} - -void _GetPPFont(HWND hwnd, char *buff) -{ - ULONG AttrFound; - BYTE AttrValue[128]; - ULONG cbRetLen; - - cbRetLen = WinQueryPresParam(hwnd, - PP_FONTNAMESIZE, - 0, - &AttrFound, - sizeof(AttrValue), - &AttrValue, - QPF_NOINHERIT); - - if(PP_FONTNAMESIZE == AttrFound && cbRetLen) - { - memcpy(buff, AttrValue, cbRetLen); - } -} - -/* Returns height of specified window. */ -int _get_height(HWND handle) -{ - unsigned long height; - dw_window_get_pos_size(handle, NULL, NULL, NULL, &height); - return (int)height; -} - -/* Find the height of the frame a desktop style window is sitting on */ -int _get_frame_height(HWND handle) -{ - while(handle) - { - HWND client; - if((client = WinWindowFromID(handle, FID_CLIENT)) != NULLHANDLE) - { - return _get_height(WinQueryWindow(handle, QW_PARENT)); - } - handle = WinQueryWindow(handle, QW_PARENT); - } - return dw_screen_height(); -} - -int _HandleScroller(HWND handle, int pos, int which) -{ - MPARAM res; - int min, max, page; - - if(which == SB_SLIDERTRACK) - return pos; - - pos = dw_scrollbar_query_pos(handle); - res = WinSendMsg(handle, SBM_QUERYRANGE, 0, 0); - - min = SHORT1FROMMP(res); - max = SHORT2FROMMP(res); - page = (int)dw_window_get_data(handle, "_dw_scrollbar_visible"); - - switch(which) - { - case SB_LINEUP: - pos = pos - 1; - if(pos < min) - pos = min; - dw_scrollbar_set_pos(handle, pos); - return pos; - case SB_LINEDOWN: - pos = pos + 1; - if(pos > max) - pos = max; - dw_scrollbar_set_pos(handle, pos); - return pos; - case SB_PAGEUP: - pos = pos - page; - if(pos < min) - pos = min; - dw_scrollbar_set_pos(handle, pos); - return pos; - case SB_PAGEDOWN: - pos = pos + page; - if(pos > max) - pos = max; - dw_scrollbar_set_pos(handle, pos); - return pos; - } - return -1; -} - -void _clear_emphasis(void) -{ - if(hwndEmph && WinIsWindow(dwhab, hwndEmph) && pCoreEmph) - WinSendMsg(hwndEmph, CM_SETRECORDEMPHASIS, pCoreEmph, MPFROM2SHORT(FALSE, CRA_SOURCE)); - hwndEmph = NULLHANDLE; - pCoreEmph = NULL; -} - -/* Find the desktop window handle */ -HWND _menu_owner(HWND handle) -{ - HWND menuowner = NULLHANDLE, lastowner = (HWND)dw_window_get_data(handle, "_dw_owner"); - int menubar = (int)dw_window_get_data(handle, "_dw_menubar"); - - /* Find the toplevel window */ - while(!menubar && (menuowner = (HWND)dw_window_get_data(lastowner, "_dw_owner")) != NULLHANDLE) - { - menubar = (int)dw_window_get_data(lastowner, "_dw_menubar"); - lastowner = menuowner; - } - if(menuowner && menubar) - { - HWND client = WinWindowFromID(menuowner, FID_CLIENT); - - return client ? client : menuowner; - } - return NULLHANDLE; -} - -MRESULT EXPENTRY _run_event(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - int result = -1; - SignalHandler *tmp = Root; - ULONG origmsg = msg; - - if(msg == WM_BUTTON2DOWN || msg == WM_BUTTON3DOWN) - msg = WM_BUTTON1DOWN; - if(msg == WM_BUTTON2UP || msg == WM_BUTTON3UP) - msg = WM_BUTTON1UP; - if(msg == WM_VSCROLL || msg == WM_HSCROLL) - msg = WM_CONTROL; - - /* Find any callbacks for this function */ - while(tmp) - { - if(tmp->message == msg || msg == WM_CONTROL || tmp->message == WM_USER+1) - { - switch(msg) - { - case WM_SETFOCUS: - { - if((mp2 && tmp->message == WM_SETFOCUS) || (!mp2 && tmp->message == WM_USER+1)) - { - int (* API setfocusfunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction; - - if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd) - { - result = setfocusfunc(tmp->window, tmp->data); - tmp = NULL; - } - } - } - break; - case WM_TIMER: - { - int (* API timerfunc)(void *) = (int (* API)(void *))tmp->signalfunction; - if(tmp->id == (int)mp1) - { - if(!timerfunc(tmp->data)) - dw_timer_disconnect(tmp->id); - tmp = NULL; - } - result = 0; - } - break; - case WM_SIZE: - { - int (* API sizefunc)(HWND, int, int, void *) = (int (* API)(HWND, int, int, void *))tmp->signalfunction; - - if((hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd) && SHORT1FROMMP(mp2) && SHORT2FROMMP(mp2)) - { - result = sizefunc(tmp->window, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2), tmp->data); - tmp = NULL; - } - } - break; - case WM_BUTTON1DOWN: - { - POINTS pts = (*((POINTS*)&mp1)); - int (* API buttonfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction; - - if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window) - { - int button = 0; - - switch(origmsg) - { - case WM_BUTTON1DOWN: - button = 1; - break; - case WM_BUTTON2DOWN: - button = 2; - break; - case WM_BUTTON3DOWN: - button = 3; - break; - } - - result = buttonfunc(tmp->window, pts.x, _get_frame_height(tmp->window) - pts.y, button, tmp->data); - tmp = NULL; - } - } - break; - case WM_BUTTON1UP: - { - POINTS pts = (*((POINTS*)&mp1)); - int (* API buttonfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction; - - if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window) - { - int button = 0; - - switch(origmsg) - { - case WM_BUTTON1UP: - button = 1; - break; - case WM_BUTTON2UP: - button = 2; - break; - case WM_BUTTON3UP: - button = 3; - break; - } - - result = buttonfunc(tmp->window, pts.x, WinQueryWindow(tmp->window, QW_PARENT) == HWND_DESKTOP ? dw_screen_height() - pts.y : _get_height(tmp->window) - pts.y, button, tmp->data); - tmp = NULL; - } - } - break; - case WM_MOUSEMOVE: - { - int (* API motionfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction; - - if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window) - { - int keys = 0; - SHORT x = SHORT1FROMMP(mp1), y = SHORT2FROMMP(mp1); - - if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000) - keys = DW_BUTTON1_MASK; - if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000) - keys |= DW_BUTTON2_MASK; - if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000) - keys |= DW_BUTTON3_MASK; - - result = motionfunc(tmp->window, x, _get_frame_height(tmp->window) - y, keys, tmp->data); - tmp = NULL; - } - } - break; - case WM_CHAR: - { - int (* API keypressfunc)(HWND, char, int, int, void *) = (int (* API)(HWND, char, int, int, void *))tmp->signalfunction; - - if((hWnd == tmp->window || _toplevel_window(hWnd) == tmp->window) && !(SHORT1FROMMP(mp1) & KC_KEYUP)) - { - int vk; - char ch = 0; - - if(SHORT1FROMMP(mp1) & KC_CHAR) - ch = (char)SHORT1FROMMP(mp2); - if(SHORT1FROMMP(mp1) & KC_VIRTUALKEY) - vk = SHORT2FROMMP(mp2); - else - vk = SHORT1FROMMP(mp2) + 128; - - /* This is a hack to fix shift presses showing - * up as tabs! - */ - if(ch == '\t' && !(SHORT1FROMMP(mp1) & KC_CHAR)) - { - ch = 0; - vk = VK_SHIFT; - } - - result = keypressfunc(tmp->window, ch, vk, - SHORT1FROMMP(mp1) & (KC_ALT | KC_SHIFT | KC_CTRL), tmp->data); - tmp = NULL; - } - } - break; - case WM_CLOSE: - { - int (* API closefunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction; - - if(hWnd == tmp->window || hWnd == WinWindowFromID(tmp->window, FID_CLIENT)) - { - result = closefunc(tmp->window, tmp->data); - if(result) - result = FALSE; - tmp = NULL; - } - } - break; - case WM_PAINT: - { - HPS hps; - DWExpose exp; - int (* API exposefunc)(HWND, DWExpose *, void *) = (int (* API)(HWND, DWExpose *, void *))tmp->signalfunction; - RECTL rc; - - if(hWnd == tmp->window) - { - int height = _get_height(hWnd); - - hps = WinBeginPaint(hWnd, 0L, &rc); - exp.x = rc.xLeft; - exp.y = height - rc.yTop - 1; - exp.width = rc.xRight - rc. xLeft; - exp.height = rc.yTop - rc.yBottom; - result = exposefunc(hWnd, &exp, tmp->data); - WinEndPaint(hps); - } - } - break; - case WM_COMMAND: - { - int (* API clickfunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction; - ULONG command = COMMANDMSG(&msg)->cmd; - - if(tmp->id && command == tmp->id) - { - HWND menuowner = _menu_owner(tmp->window); - - if(menuowner == hWnd || menuowner == NULLHANDLE) - { - result = clickfunc(tmp->window, tmp->data); - tmp = NULL; - } - } - else if(tmp->window < 65536 && command == tmp->window) - { - result = clickfunc(popup ? popup : tmp->window, tmp->data); - tmp = NULL; - } - } - break; - case WM_CONTROL: - if(origmsg == WM_VSCROLL || origmsg == WM_HSCROLL || tmp->message == SHORT2FROMMP(mp1) || - (tmp->message == SLN_SLIDERTRACK && SHORT2FROMMP(mp1) == SLN_CHANGE)) - { - int svar = SLN_SLIDERTRACK; - if(origmsg == WM_CONTROL) - svar = SHORT2FROMMP(mp1); - - switch(svar) - { - case CN_ENTER: - { - int (* API containerselectfunc)(HWND, char *, void *) = (int (* API)(HWND, char *, void *))tmp->signalfunction; - int id = SHORT1FROMMP(mp1); - HWND conthwnd = dw_window_from_id(hWnd, id); - char *text = NULL; - - if(mp2) - { - PRECORDCORE pre; - - pre = ((PNOTIFYRECORDENTER)mp2)->pRecord; - if(pre) - text = pre->pszIcon; - } - - if(tmp->window == conthwnd) - { - result = containerselectfunc(tmp->window, text, tmp->data); - tmp = NULL; - } - } - break; - case CN_EXPANDTREE: - { - int (* API treeexpandfunc)(HWND, HTREEITEM, void *) = (int (* API)(HWND, HTREEITEM, void *))tmp->signalfunction; - int id = SHORT1FROMMP(mp1); - HWND conthwnd = dw_window_from_id(hWnd, id); - - if(tmp->window == conthwnd) - { - result = treeexpandfunc(tmp->window, (HTREEITEM)mp2, tmp->data); - tmp = NULL; - } - } - break; - case CN_CONTEXTMENU: - { - int (* API containercontextfunc)(HWND, char *, int, int, void *, void *) = (int (* API)(HWND, char *, int, int, void *, void *))tmp->signalfunction; - int id = SHORT1FROMMP(mp1); - HWND conthwnd = dw_window_from_id(hWnd, id); - char *text = NULL; - void *user = NULL; - LONG x,y; - - if(mp2) - { - PCNRITEM pci; - - pci = (PCNRITEM)mp2; - - text = pci->rc.pszIcon; - user = pci->user; - } - - dw_pointer_query_pos(&x, &y); - - if(tmp->window == conthwnd) - { - int container = (int)dw_window_get_data(tmp->window, "_dw_container"); - - if(mp2) - { - if(!container) - { - NOTIFYRECORDEMPHASIS pre; - - dw_tree_item_select(tmp->window, (HTREEITEM)mp2); - pre.pRecord = mp2; - pre.fEmphasisMask = CRA_CURSORED; - pre.hwndCnr = tmp->window; - _run_event(hWnd, WM_CONTROL, MPFROM2SHORT(0, CN_EMPHASIS), (MPARAM)&pre); - pre.pRecord->flRecordAttr |= CRA_CURSORED; - } - else - { - if(pCoreEmph) - _clear_emphasis(); - hwndEmph = tmp->window; - pCoreEmph = mp2; - WinSendMsg(tmp->window, CM_SETRECORDEMPHASIS, mp2, MPFROM2SHORT(TRUE, CRA_SOURCE)); - } - } - result = containercontextfunc(tmp->window, text, x, y, tmp->data, user); - tmp = NULL; - } - } - break; - case CN_EMPHASIS: - { - PNOTIFYRECORDEMPHASIS pre = (PNOTIFYRECORDEMPHASIS)mp2; - static int emph_recurse = 0; - - if(!emph_recurse) - { - emph_recurse = 1; - - if(mp2) - { - if(tmp->window == pre->hwndCnr) - { - PCNRITEM pci = (PCNRITEM)pre->pRecord; - - if(pci && pre->fEmphasisMask & CRA_CURSORED && (pci->rc.flRecordAttr & CRA_CURSORED)) - { - int (* API treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = (int (* API)(HWND, HTREEITEM, char *, void *, void *))tmp->signalfunction; - - if(dw_window_get_data(tmp->window, "_dw_container")) - result = treeselectfunc(tmp->window, 0, pci->rc.pszIcon, tmp->data, 0); - else - { - if(lasthcnr == tmp->window && lastitem == (HWND)pci) - { - lasthcnr = 0; - lastitem = 0; - } - else - { - lasthcnr = tmp->window; - lastitem = (HWND)pci; - result = treeselectfunc(tmp->window, (HTREEITEM)pci, pci->rc.pszIcon, tmp->data, pci->user); - } - } - tmp = NULL; - } - } - } - emph_recurse = 0; - } - } - break; - case LN_SELECT: - { - char classbuf[100]; - - WinQueryClassName(tmp->window, 99, classbuf); - - if(strncmp(classbuf, "#38", 4) == 0) - { - int (* API valuechangedfunc)(HWND, int, void *) = (int (* API)(HWND, int, void *))tmp->signalfunction; - - if(tmp->window == hWnd || WinQueryWindow(tmp->window, QW_PARENT) == hWnd) - { - static int lastvalue = -1; - static HWND lasthwnd = NULLHANDLE; - int ulValue = (int)WinSendMsg(tmp->window, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0); - if(lastvalue != ulValue || lasthwnd != tmp->window) - { - result = valuechangedfunc(tmp->window, ulValue, tmp->data); - lastvalue = ulValue; - lasthwnd = tmp->window; - } - tmp = NULL; - } - } - else - { - int (* API listboxselectfunc)(HWND, int, void *) = (int (* API )(HWND, int, void *))tmp->signalfunction; - int id = SHORT1FROMMP(mp1); - HWND conthwnd = dw_window_from_id(hWnd, id); - static int _recursing = 0; - - if(_recursing == 0 && (tmp->window == conthwnd || (!id && tmp->window == (HWND)mp2))) - { - char buf1[500]; - unsigned int index = dw_listbox_selected(tmp->window); - - dw_listbox_query_text(tmp->window, index, buf1, 500); - - _recursing = 1; - - if(id && strncmp(classbuf, "#2", 3)==0) - { - char *buf2; - - buf2 = dw_window_get_text(tmp->window); - - /* This is to make sure the listboxselect function doesn't - * get called if the user is modifying the entry text. - */ - if(buf2 && *buf2 && *buf1 && strncmp(buf1, buf2, 500) == 0) - result = listboxselectfunc(tmp->window, index, tmp->data); - - if(buf2) - free(buf2); - } - else - result = listboxselectfunc(tmp->window, index, tmp->data); - - _recursing = 0; - tmp = NULL; - } - } - } - break; - case SLN_SLIDERTRACK: - { - int (* API valuechangedfunc)(HWND, int, void *) = (int (* API)(HWND, int, void *))tmp->signalfunction; - - if(origmsg == WM_CONTROL) - { - /* Handle Slider control */ - if(tmp->window == hWnd || WinQueryWindow(tmp->window, QW_PARENT) == hWnd) - { - static int lastvalue = -1; - static HWND lasthwnd = NULLHANDLE; - int ulValue = (int)WinSendMsg(tmp->window, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0); - if(lastvalue != ulValue || lasthwnd != tmp->window) - { - dw_window_set_data(tmp->window, "_dw_slider_value", (void *)ulValue); - result = valuechangedfunc(tmp->window, ulValue, tmp->data); - lastvalue = ulValue; - lasthwnd = tmp->window; - } - tmp = NULL; - } - } - else - { - /* Handle scrollbar control */ - if(tmp->window > 65535 && tmp->window == WinWindowFromID(hWnd, (ULONG)mp1)) - { - int pos = _HandleScroller(tmp->window, (int)SHORT1FROMMP(mp2), (int)SHORT2FROMMP(mp2));; - - if(pos > -1) - { - dw_window_set_data(tmp->window, "_dw_scrollbar_value", (void *)pos); - result = valuechangedfunc(tmp->window, pos, tmp->data); - } - result = 0; - tmp = NULL; - } - } - } - break; - case BKN_PAGESELECTED: - { - PAGESELECTNOTIFY *psn = (PAGESELECTNOTIFY *)mp2; - - if(psn && tmp->window == psn->hwndBook) - { - int (* API switchpagefunc)(HWND, unsigned long, void *) = (int (* API)(HWND, unsigned long, void *))tmp->signalfunction; - - result = switchpagefunc(tmp->window, psn->ulPageIdNew, tmp->data); - tmp = NULL; - } - } - break; - } - } - break; - } - } - - if(tmp) - tmp = tmp->next; - - } - return (MRESULT)result; -} - -/* Handles control messages sent to the box (owner). */ -MRESULT EXPENTRY _controlproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - Box *blah = WinQueryWindowPtr(hWnd, QWP_USER); - - switch(msg) - { - case WM_VSCROLL: - case WM_HSCROLL: - if(_run_event(hWnd, msg, mp1, mp2)) - { - HWND window = WinWindowFromID(hWnd, (ULONG)mp1); - _HandleScroller(window, (int)SHORT1FROMMP(mp2), (int)SHORT2FROMMP(mp2)); - } - break; - case WM_CONTROL: - _run_event(hWnd, msg, mp1, mp2); - break; - } - - if(blah && blah->oldproc) - return blah->oldproc(hWnd, msg, mp1, mp2); - - return WinDefWindowProc(hWnd, msg, mp1, mp2); -} - -/* The main window procedure for Dynamic Windows, all the resizing code is done here. */ -MRESULT EXPENTRY _wndproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - int result = -1; - static int command_active = 0; - void (* API windowfunc)(PVOID) = 0L; - - if(!command_active) - { - /* Make sure we don't end up in infinite recursion */ - command_active = 1; - - result = (int)_run_event(hWnd, msg, mp1, mp2); - - command_active = 0; - } - - /* Now that any handlers are done... do normal processing */ - switch( msg ) - { - case WM_ERASEBACKGROUND: - return 0; - - case WM_PAINT: - { - HPS hps; - RECTL rc; - - hps = WinBeginPaint( hWnd, 0L, &rc ); - WinEndPaint( hps ); - break; - } - - case WM_SIZE: - { - Box *mybox = (Box *)WinQueryWindowPtr(hWnd, QWP_USER); - - if(!SHORT1FROMMP(mp2) && !SHORT2FROMMP(mp2)) - return (MPARAM)TRUE; - - if(mybox && mybox->flags != DW_MINIMIZED) - { - /* Hide the window when recalculating to reduce - * CPU load. - */ - WinShowWindow(hWnd, FALSE); - - _do_resize(mybox, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2)); - - WinShowWindow(hWnd, TRUE); - } - } - break; - case WM_MINMAXFRAME: - { - Box *mybox = (Box *)WinQueryWindowPtr(hWnd, QWP_USER); - SWP *swp = (SWP *)mp1; - - if(mybox && (swp->fl & SWP_MINIMIZE)) - mybox->flags = DW_MINIMIZED; - - if(mybox && (swp->fl & SWP_RESTORE)) - { - if(!mybox->titlebar && mybox->hwndtitle) - WinSetParent(mybox->hwndtitle, HWND_OBJECT, FALSE); - mybox->flags = 0; - } - - if(mybox && (swp->fl & SWP_MAXIMIZE)) - { - int z; - SWP swp2; - - WinQueryWindowPos(swp->hwnd, &swp2); - - if(swp2.cx == swp->cx && swp2.cy == swp->cy) - return FALSE; - - mybox->flags = 0; - - /* Hide the window when recalculating to reduce - * CPU load. - */ - WinShowWindow(hWnd, FALSE); - - _do_resize(mybox, swp->cx, swp->cy); - - if(mybox->count == 1 && mybox->items[0].type == TYPEBOX) - { - mybox = (Box *)WinQueryWindowPtr(mybox->items[0].hwnd, QWP_USER); - - for(z=0;z<mybox->count;z++) - _check_resize_notebook(mybox->items[z].hwnd); - - } - - WinShowWindow(hWnd, TRUE); - } - } - break; - case WM_CONTROL: - switch(SHORT2FROMMP(mp1)) - { - case BKN_PAGESELECTEDPENDING: - { - PAGESELECTNOTIFY *psn = (PAGESELECTNOTIFY *)mp2; - HWND pagehwnd = (HWND)WinSendMsg(psn->hwndBook, BKM_QUERYPAGEWINDOWHWND, MPFROMLONG(psn->ulPageIdNew), 0); - Box *pagebox = (Box *)WinQueryWindowPtr(pagehwnd, QWP_USER); - unsigned long x, y, width, height; - RECTL rc; - - if(pagebox && psn->ulPageIdNew != psn->ulPageIdCur) - { - dw_window_get_pos_size(psn->hwndBook, &x, &y, &width, &height); - - rc.xLeft = x; - rc.yBottom = y; - rc.xRight = x + width; - rc.yTop = y + height; - - WinSendMsg(psn->hwndBook, BKM_CALCPAGERECT, (MPARAM)&rc, (MPARAM)TRUE); - - _do_resize(pagebox, rc.xRight - rc.xLeft, rc.yTop - rc.yBottom); - } - } - break; - } - break; - case WM_CLOSE: - if(result == -1) - { - dw_window_destroy(WinQueryWindow(hWnd, QW_PARENT)); - return (MRESULT)TRUE; - } - break; - case WM_MOUSEMOVE: - { - HPOINTER ptr = (HPOINTER)dw_window_get_data(hWnd, "_dw_pointer"); - - if(ptr) - WinSetPointer(HWND_DESKTOP, ptr); - } - break; - case WM_USER: - windowfunc = (void (* API)(void *))mp1; - - if(windowfunc) - windowfunc((void *)mp2); - break; - case WM_CHAR: - if(SHORT1FROMMP(mp2) == '\t') - { - if(CHARMSG(&msg)->fs & KC_SHIFT) - _shift_focus_back(hWnd); - else - _shift_focus(hWnd); - return FALSE; - } - break; - case WM_DESTROY: - { - HWND parent = WinQueryWindow(hWnd, QW_PARENT); - - /* Free memory before destroying */ - if(parent && WinWindowFromID(parent, FID_CLIENT) == hWnd) - _free_window_memory(parent); - else - _free_window_memory(hWnd); - } - break; - case WM_MENUEND: - _clear_emphasis(); - if(dw_window_get_data((HWND)mp2, "_dw_popup")) - _free_menu_data((HWND)mp2); - break; - } - - if(result != -1) - return (MRESULT)result; - else - return WinDefWindowProc(hWnd, msg, mp1, mp2); -} - -void _changebox(Box *thisbox, int percent, int type) -{ - int z; - - for(z=0;z<thisbox->count;z++) - { - if(thisbox->items[z].type == TYPEBOX) - { - Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER); - _changebox(tmp, percent, type); - } - else - { - if(type == DW_HORZ) - { - if(thisbox->items[z].hsize == SIZEEXPAND) - thisbox->items[z].width = (int)(((float)thisbox->items[z].origwidth) * (((float)percent)/((float)100.0))); - } - else - { - if(thisbox->items[z].vsize == SIZEEXPAND) - thisbox->items[z].height = (int)(((float)thisbox->items[z].origheight) * (((float)percent)/((float)100.0))); - } - } - } -} - -void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y) -{ - if(type == DW_HORZ) - { - int newx = x; - float ratio = (float)percent/(float)100.0; - HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_topleft"); - HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright"); - Box *tmp = WinQueryWindowPtr(handle1, QWP_USER); - - WinShowWindow(handle1, FALSE); - WinShowWindow(handle2, FALSE); - - newx = (int)((float)newx * ratio) - (SPLITBAR_WIDTH/2); - - WinSetWindowPos(handle1, NULLHANDLE, 0, 0, newx, y, SWP_MOVE | SWP_SIZE); - _do_resize(tmp, newx - 1, y - 1); - - dw_window_set_data(hwnd, "_dw_start", (void *)newx); - - tmp = WinQueryWindowPtr(handle2, QWP_USER); - - newx = x - newx - SPLITBAR_WIDTH; - - WinSetWindowPos(handle2, NULLHANDLE, x - newx, 0, newx, y, SWP_MOVE | SWP_SIZE); - _do_resize(tmp, newx - 1, y - 1); - - WinShowWindow(handle1, TRUE); - WinShowWindow(handle2, TRUE); - } - else - { - int newy = y; - float ratio = (float)percent/(float)100.0; - HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_topleft"); - HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright"); - Box *tmp = WinQueryWindowPtr(handle1, QWP_USER); - - WinShowWindow(handle1, FALSE); - WinShowWindow(handle2, FALSE); - - newy = (int)((float)newy * ratio) - (SPLITBAR_WIDTH/2); - - WinSetWindowPos(handle1, NULLHANDLE, 0, y - newy, x, newy, SWP_MOVE | SWP_SIZE); - _do_resize(tmp, x - 1, newy - 1); - - tmp = WinQueryWindowPtr(handle2, QWP_USER); - - newy = y - newy - SPLITBAR_WIDTH; - - WinSetWindowPos(handle2, NULLHANDLE, 0, 0, x, newy, SWP_MOVE | SWP_SIZE); - _do_resize(tmp, x - 1, newy - 1); - - WinShowWindow(handle1, TRUE); - WinShowWindow(handle2, TRUE); - - dw_window_set_data(hwnd, "_dw_start", (void *)newy); - } -} - - -/* This handles any activity on the splitbars (sizers) */ -MRESULT EXPENTRY _splitwndproc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - float *percent = (float *)dw_window_get_data(hwnd, "_dw_percent"); - int type = (int)dw_window_get_data(hwnd, "_dw_type"); - int start = (int)dw_window_get_data(hwnd, "_dw_start"); - - switch (msg) - { - case WM_ACTIVATE: - case WM_SETFOCUS: - return (MRESULT)(FALSE); - - case WM_PAINT: - { - HPS hps; - POINTL ptl[2]; - RECTL rcl; - - hps = WinBeginPaint(hwnd, 0, 0); - - WinQueryWindowRect(hwnd, &rcl); - - if(type == DW_HORZ) - { - ptl[0].x = rcl.xLeft + start; - ptl[0].y = rcl.yBottom; - ptl[1].x = rcl.xRight + start + 3; - ptl[1].y = rcl.yTop; - } - else - { - ptl[0].x = rcl.xLeft; - ptl[0].y = rcl.yBottom + start; - ptl[1].x = rcl.xRight; - ptl[1].y = rcl.yTop + start + 3; - } - - - GpiSetColor(hps, CLR_PALEGRAY); - GpiMove(hps, &ptl[0]); - GpiBox(hps, DRO_OUTLINEFILL, &ptl[1], 0, 0); - WinEndPaint(hps); - } - return MRFROMSHORT(FALSE); - - case WM_MOUSEMOVE: - { - if(type == DW_HORZ) - WinSetPointer(HWND_DESKTOP, - WinQuerySysPointer(HWND_DESKTOP, - SPTR_SIZEWE, - FALSE)); - else - WinSetPointer(HWND_DESKTOP, - WinQuerySysPointer(HWND_DESKTOP, - SPTR_SIZENS, - FALSE)); - } - return MRFROMSHORT(FALSE); - case WM_BUTTON1DOWN: - { - APIRET rc; - RECTL rclFrame; - RECTL rclBounds; - - WinQueryWindowRect(hwnd, &rclFrame); - WinQueryWindowRect(hwnd, &rclBounds); - - WinMapWindowPoints(hwnd, HWND_DESKTOP, - (PPOINTL)&rclBounds, 2); - - - if(type == DW_HORZ) - { - rclFrame.xLeft = start; - rclFrame.xRight = start + SPLITBAR_WIDTH; - } - else - { - rclFrame.yBottom = start; - rclFrame.yTop = start + SPLITBAR_WIDTH; - } - - if(percent) - { - rc = _TrackRectangle(hwnd, &rclFrame, &rclBounds); - - if(rc == TRUE) - { - int width = (rclBounds.xRight - rclBounds.xLeft); - int height = (rclBounds.yTop - rclBounds.yBottom); - - if(type == DW_HORZ) - { - start = rclFrame.xLeft - rclBounds.xLeft; - if(width - SPLITBAR_WIDTH > 1 && start < width - SPLITBAR_WIDTH) - *percent = ((float)start / (float)(width - SPLITBAR_WIDTH)) * 100.0; - } - else - { - start = rclFrame.yBottom - rclBounds.yBottom; - if(height - SPLITBAR_WIDTH > 1 && start < height - SPLITBAR_WIDTH) - *percent = 100.0 - (((float)start / (float)(height - SPLITBAR_WIDTH)) * 100.0); - } - _handle_splitbar_resize(hwnd, *percent, type, width, height); - } - } - } - return MRFROMSHORT(FALSE); - } - return WinDefWindowProc(hwnd, msg, mp1, mp2); -} - -/* Function: BubbleProc - * Abstract: Subclass procedure for bubble help - */ -MRESULT EXPENTRY _BubbleProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - MRESULT res; - PFNWP proc = (PFNWP)WinQueryWindowPtr(hwnd, QWL_USER); - - if(proc) - res = proc(hwnd, msg, mp1, mp2); - else - res = WinDefWindowProc(hwnd, msg, mp1, mp2); - - if(msg == WM_PAINT) - { - POINTL ptl; - HPS hpsTemp; - RECTL rcl; - int height, width; - - WinQueryWindowRect(hwnd, &rcl); - height = rcl.yTop - rcl.yBottom - 1; - width = rcl.xRight - rcl.xLeft - 1; - - /* Draw a border around the bubble help */ - hpsTemp = WinGetPS(hwnd); - GpiSetColor(hpsTemp, CLR_BLACK); - ptl.x = ptl.y = 0; - GpiMove(hpsTemp, &ptl); - ptl.x = 0; - ptl.y = height; - GpiLine(hpsTemp, &ptl); - ptl.x = ptl.y = 0; - GpiMove(hpsTemp, &ptl); - ptl.y = 0; - ptl.x = width; - GpiLine(hpsTemp, &ptl); - ptl.x = width; - ptl.y = height; - GpiMove(hpsTemp, &ptl); - ptl.x = 0; - ptl.y = height; - GpiLine(hpsTemp, &ptl); - ptl.x = width; - ptl.y = height; - GpiMove(hpsTemp, &ptl); - ptl.y = 0; - ptl.x = width; - GpiLine(hpsTemp, &ptl); - WinReleasePS(hpsTemp); - } - return res; -} - -MRESULT EXPENTRY _button_draw(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2, PFNWP oldproc, int indent) -{ - HPIXMAP pixmap = (HPIXMAP)dw_window_get_data(hwnd, "_dw_hpixmap"); - HPIXMAP disable = (HPIXMAP)dw_window_get_data(hwnd, "_dw_hpixmap_disabled"); - MRESULT res; - - if(!oldproc) - res = WinDefWindowProc(hwnd, msg, mp1, mp2); - res = oldproc(hwnd, msg, mp1, mp2); - - if(pixmap) - { - unsigned long width, height; - int x, y; - - dw_window_get_pos_size(hwnd, NULL, NULL, &width, &height); - - x = (width - pixmap->width)/2; - y = (height - pixmap->height)/2; - - if(disable && dw_window_get_data(hwnd, "_dw_disabled")) - dw_pixmap_bitblt(hwnd, 0, x + indent, y + indent, pixmap->width, pixmap->height, 0, disable, 0, 0); - else - dw_pixmap_bitblt(hwnd, 0, x + indent, y + indent, pixmap->width, pixmap->height, 0, pixmap, 0, 0); - } - return res; -} - -/* Function: BtProc - * Abstract: Subclass procedure for buttons - */ - -MRESULT EXPENTRY _BtProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - BubbleButton *bubble; - PFNWP oldproc; - - bubble = (BubbleButton *)WinQueryWindowPtr(hwnd, QWL_USER); - - if(!bubble) - return WinDefWindowProc(hwnd, msg, mp1, mp2); - - oldproc = bubble->pOldProc; - - switch(msg) - { - case WM_PAINT: - return _button_draw(hwnd, msg, mp1, mp2, oldproc, 0); - case BM_SETHILITE: - return _button_draw(hwnd, msg, mp1, mp2, oldproc, (int)mp1); - case WM_SETFOCUS: - if(mp2) - _run_event(hwnd, msg, mp1, mp2); - else - WinSendMsg(hwnd, BM_SETDEFAULT, 0, 0); - break; - case WM_BUTTON1DOWN: - case WM_BUTTON2DOWN: - case WM_BUTTON3DOWN: - case WM_BUTTON1DBLCLK: - case WM_BUTTON2DBLCLK: - case WM_BUTTON3DBLCLK: - if(dw_window_get_data(hwnd, "_dw_disabled")) - return (MRESULT)FALSE; - break; - case WM_BUTTON1UP: - { - SignalHandler *tmp = Root; - - if(WinIsWindowEnabled(hwnd) && !dw_window_get_data(hwnd, "_dw_disabled")) - { - /* Find any callbacks for this function */ - while(tmp) - { - if(tmp->message == WM_COMMAND) - { - /* Make sure it's the right window, and the right ID */ - if(tmp->window == hwnd) - { - /* Due to the fact that if we run the function - * here, finishing actions on the button will occur - * after we run the signal handler. So we post the - * message so the button can finish what it needs to - * do before we run our handler. - */ - WinPostMsg(hwnd, WM_USER, (MPARAM)tmp, 0); - tmp = NULL; - } - } - if(tmp) - tmp= tmp->next; - } - } - } - break; - case WM_USER: - { - SignalHandler *tmp = (SignalHandler *)mp1; - int (* API clickfunc)(HWND, void *) = NULL; - - if(tmp) - { - clickfunc = (int (* API)(HWND, void *))tmp->signalfunction; - - clickfunc(tmp->window, tmp->data); - } - } - break; - case WM_CHAR: - { - /* A button press should also occur for an ENTER or SPACE press - * while the button has the active input focus. - */ - if(SHORT1FROMMP(mp2) == '\r' || SHORT1FROMMP(mp2) == ' ') - { - SignalHandler *tmp = Root; - - /* Find any callbacks for this function */ - while(tmp) - { - if(tmp->message == WM_COMMAND) - { - /* Make sure it's the right window, and the right ID */ - if(tmp->window == hwnd) - { - WinPostMsg(hwnd, WM_USER, (MPARAM)tmp, 0); - tmp = NULL; - } - } - if(tmp) - tmp= tmp->next; - } - } - if(SHORT1FROMMP(mp2) == '\t') - { - if(CHARMSG(&msg)->fs & KC_SHIFT) - _shift_focus_back(hwnd); - else - _shift_focus(hwnd); - 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); - return FALSE; - } - else if(!(CHARMSG(&msg)->fs & KC_KEYUP) && (CHARMSG(&msg)->vkey == VK_RIGHT || CHARMSG(&msg)->vkey == VK_DOWN)) - { - _shift_focus(hwnd); - return FALSE; - } - } - break; - case 0x041f: - if (hwndBubble) - { - WinDestroyWindow(hwndBubble); - hwndBubble = 0; - } - break; - - case 0x041e: - - if(!*bubble->bubbletext) - break; - - if(hwndBubble) - { - WinDestroyWindow(hwndBubble); - hwndBubble = 0; - } - - if(!hwndBubble) - { - HPS hpsTemp = 0; - LONG lHight; - LONG lWidth; - POINTL txtPointl[TXTBOX_COUNT]; - POINTL ptlWork = {0,0}; - ULONG ulColor = CLR_YELLOW; - void *blah; - - hwndBubbleLast = hwnd; - hwndBubble = WinCreateWindow(HWND_DESKTOP, - WC_STATIC, - "", - SS_TEXT | - DT_CENTER | - DT_VCENTER, - 0,0,0,0, - HWND_DESKTOP, - HWND_TOP, - 0, - NULL, - NULL); - - WinSetPresParam(hwndBubble, - PP_FONTNAMESIZE, - strlen(DefaultFont)+1, - DefaultFont); - - - WinSetPresParam(hwndBubble, - PP_BACKGROUNDCOLORINDEX, - sizeof(ulColor), - &ulColor); - - WinSetWindowText(hwndBubble, - bubble->bubbletext); - - WinMapWindowPoints(hwnd, HWND_DESKTOP, &ptlWork, 1); - - hpsTemp = WinGetPS(hwndBubble); - GpiQueryTextBox(hpsTemp, - strlen(bubble->bubbletext), - bubble->bubbletext, - TXTBOX_COUNT, - txtPointl); - WinReleasePS(hpsTemp); - - lWidth = txtPointl[TXTBOX_TOPRIGHT].x - - txtPointl[TXTBOX_TOPLEFT ].x + 8; - - lHight = txtPointl[TXTBOX_TOPLEFT].y - - txtPointl[TXTBOX_BOTTOMLEFT].y + 8; - - ptlWork.y -= lHight; - - blah = (void *)WinSubclassWindow(hwndBubble, _BubbleProc); - - if(blah) - WinSetWindowPtr(hwndBubble, QWP_USER, blah); - - WinSetWindowPos(hwndBubble, - HWND_TOP, - ptlWork.x, - ptlWork.y, - lWidth, - lHight, - SWP_SIZE | SWP_MOVE | SWP_SHOW); - } - break; - } - - if(!oldproc) - return WinDefWindowProc(hwnd, msg, mp1, mp2); - return oldproc(hwnd, msg, mp1, mp2); -} - -MRESULT EXPENTRY _RendProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) -{ - int res = 0; - res = (int)_run_event(hwnd, msg, mp1, mp2); - switch(msg) - { - case WM_BUTTON1DOWN: - case WM_BUTTON2DOWN: - case WM_BUTTON3DOWN: - if(res == -1) - WinSetFocus(HWND_DESKTOP, hwnd); - else if(res) - return (MPARAM)TRUE; - } - return WinDefWindowProc(hwnd, msg, mp1, mp2); -} - -MRESULT EXPENTRY _TreeProc(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: - { - HPS hps; - RECTL rcl; - POINTL ptl[2]; - - if(oldproc) - oldproc(hwnd, msg, mp1, mp2); - - hps = WinBeginPaint(hwnd, 0, 0); - WinQueryWindowRect(hwnd, &rcl); - ptl[0].x = rcl.xLeft + 1; - ptl[0].y = rcl.yBottom + 1; - ptl[1].x = rcl.xRight - 1; - ptl[1].y = rcl.yTop - 1; - - GpiSetColor(hps, CLR_BLACK); - GpiMove(hps, &ptl[0]); - GpiBox(hps, DRO_OUTLINE, &ptl[1], 0, 0); - WinEndPaint(hps); - } - return MRFROMSHORT(FALSE); - case WM_SETFOCUS: - _run_event(hwnd, msg, mp1, mp2); - break; - case WM_CHAR: - if(SHORT1FROMMP(mp2) == '\t') - { - if(CHARMSG(&msg)->fs & KC_SHIFT) - _shift_focus_back(hwnd); - else - _shift_focus(hwnd); - return FALSE; - } - break; - } - - _run_event(hwnd, msg, mp1, mp2); - - if(oldproc) - return oldproc(hwnd, msg, mp1, mp2); - - return WinDefWindowProc(hwnd, msg, mp1, mp2); -} - -/* - * Initializes the Dynamic Windows engine. - * Parameters: - * newthread: True if this is the only thread. - * False if there is already a message loop running. - */ -int API dw_init(int newthread, int argc, char *argv[]) -{ - APIRET rc; - - argc = argc; /* keep compiler happy */ - argv = argv; /* keep compiler happy */ - if(newthread) - { - dwhab = WinInitialize(0); - dwhmq = WinCreateMsgQueue(dwhab, 0); - } - - rc = WinRegisterClass(dwhab, ClassName, _wndproc, CS_SIZEREDRAW | CS_CLIPCHILDREN, 32); - rc = WinRegisterClass(dwhab, SplitbarClassName, _splitwndproc, 0L, 32); - - /* Get the OS/2 version. */ - DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_MS_COUNT,(void *)aulBuffer, 4*sizeof(ULONG)); - - desktop = WinQueryDesktopWindow(dwhab, NULLHANDLE); - - if(!IS_WARP4()) - DefaultFont = "8.Helv"; - - /* This is a window that hangs around as long as the - * application does and handles menu messages. - */ - hwndApp = dw_window_new(HWND_OBJECT, "", 0); - - return rc; -} - -/* - * Runs a message loop for Dynamic Windows. - */ -void API dw_main(void) -{ - QMSG qmsg; - - _dwtid = dw_thread_id(); - - while(WinGetMsg(dwhab, &qmsg, 0, 0, 0)) - { - if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) - _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); - WinDispatchMsg(dwhab, &qmsg); - } - - WinDestroyMsgQueue(dwhmq); - WinTerminate(dwhab); -} - -/* - * Runs a message loop for Dynamic Windows, for a period of milliseconds. - * Parameters: - * milliseconds: Number of milliseconds to run the loop for. - */ -void API dw_main_sleep(int milliseconds) -{ - QMSG qmsg; -#ifdef __EMX__ - struct timeval tv, start; - - gettimeofday(&start, NULL); - gettimeofday(&tv, NULL); - - while(((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000) <= milliseconds) - { - if(WinPeekMsg(dwhab, &qmsg, 0, 0, 0, PM_NOREMOVE)) - { - WinGetMsg(dwhab, &qmsg, 0, 0, 0); - if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) - _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); - WinDispatchMsg(dwhab, &qmsg); - } - else - DosSleep(1); - gettimeofday(&tv, NULL); - } -#else - double start = (double)clock(); - - while(((clock() - start) / (CLOCKS_PER_SEC/1000)) <= milliseconds) - { - if(WinPeekMsg(dwhab, &qmsg, 0, 0, 0, PM_NOREMOVE)) - { - WinGetMsg(dwhab, &qmsg, 0, 0, 0); - if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) - _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); - WinDispatchMsg(dwhab, &qmsg); - } - else - DosSleep(1); - } -#endif -} - -/* - * Processes a single message iteration and returns. - */ -void API dw_main_iteration(void) -{ - QMSG qmsg; - - _dwtid = dw_thread_id(); - - if(WinGetMsg(dwhab, &qmsg, 0, 0, 0)) - { - if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) - _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); - WinDispatchMsg(dwhab, &qmsg); - } -} - -/* - * Free's memory allocated by dynamic windows. - * Parameters: - * ptr: Pointer to dynamic windows allocated - * memory to be free()'d. - */ -void API dw_free(void *ptr) -{ - free(ptr); -} - -/* - * Allocates and initializes a dialog struct. - * Parameters: - * data: User defined data to be passed to functions. - */ -DWDialog * API dw_dialog_new(void *data) -{ - DWDialog *tmp = malloc(sizeof(DWDialog)); - - tmp->eve = dw_event_new(); - dw_event_reset(tmp->eve); - tmp->data = data; - tmp->done = FALSE; - tmp->result = NULL; - - return tmp; -} - -/* - * Accepts a dialog struct and returns the given data to the - * initial called of dw_dialog_wait(). - * Parameters: - * dialog: Pointer to a dialog struct aquired by dw_dialog_new). - * result: Data to be returned by dw_dialog_wait(). - */ -int API dw_dialog_dismiss(DWDialog *dialog, void *result) -{ - dialog->result = result; - dw_event_post(dialog->eve); - dialog->done = TRUE; - return 0; -} - -/* - * Accepts a dialog struct waits for dw_dialog_dismiss() to be - * called by a signal handler with the given dialog struct. - * Parameters: - * dialog: Pointer to a dialog struct aquired by dw_dialog_new). - */ -void * API dw_dialog_wait(DWDialog *dialog) -{ - QMSG qmsg; - void *tmp; - - while (WinGetMsg(dwhab, &qmsg, 0, 0, 0)) - { - if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) - _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); - WinDispatchMsg(dwhab, &qmsg); - if(dialog->done) - break; - } - dw_event_close(&dialog->eve); - tmp = dialog->result; - free(dialog); - return tmp; -} - - -/* - * Displays a Message Box with given text and title.. - * Parameters: - * title: The title of the message box. - * flags: flags to indicate buttons and icon - * format: printf style format string. - * ...: Additional variables for use in the format. - */ -int API dw_messagebox(char *title, int flags, char *format, ...) -{ - va_list args; - char outbuf[1024]; - int rc; - - va_start(args, format); - vsprintf(outbuf, format, args); - va_end(args); - - rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, outbuf, title, 0, flags | MB_MOVEABLE); - if(rc == MBID_OK) - return DW_MB_RETURN_OK; - else if(rc == MBID_YES) - return DW_MB_RETURN_YES; - else if(rc == MBID_NO) - return DW_MB_RETURN_NO; - else if(rc == MBID_CANCEL) - return DW_MB_RETURN_CANCEL; - else return 0; -} - -/* - * Makes the window topmost. - * Parameters: - * handle: The window handle to make topmost. - */ -int API dw_window_raise(HWND handle) -{ - return WinSetWindowPos(handle, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER); -} - -/* - * Makes the window bottommost. - * Parameters: - * handle: The window handle to make bottommost. - */ -int API dw_window_lower(HWND handle) -{ - return WinSetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER); -} - -/* - * Makes the window visible. - * Parameters: - * handle: The window handle to make visible. - */ -int API dw_window_show(HWND handle) -{ - int rc = WinSetWindowPos(handle, NULLHANDLE, 0, 0, 0, 0, SWP_SHOW); - HSWITCH hswitch; - SWCNTRL swcntrl; - - _fix_button_owner(_toplevel_window(handle), 0); - WinSetFocus(HWND_DESKTOP, handle); - _initial_focus(handle); - - /* If this window has a switch list entry make sure it is visible */ - hswitch = WinQuerySwitchHandle(handle, 0); - if(hswitch) - { - WinQuerySwitchEntry(hswitch, &swcntrl); - swcntrl.uchVisibility = SWL_VISIBLE; - WinChangeSwitchEntry(hswitch, &swcntrl); - } - if(WinWindowFromID(handle, FID_CLIENT)) - { - WindowData *blah = WinQueryWindowPtr(handle, QWP_USER); - - if(blah && !(blah->flags & DW_OS2_NEW_WINDOW)) - { - ULONG cx = dw_screen_width(), cy = dw_screen_height(); - int newx, newy, changed = 0; - SWP swp; - - blah->flags |= DW_OS2_NEW_WINDOW; - - WinQueryWindowPos(handle, &swp); - - newx = swp.x; - newy = swp.y; - - if((swp.x+swp.cx) > cx) - { - newx = (cx - swp.cx)/2; - changed = 1; - } - if((swp.y+swp.cy) > cy) - { - newy = (cy - swp.cy)/2; - changed = 1; - } - if(changed) - WinSetWindowPos(handle, NULLHANDLE, newx, newy, 0, 0, SWP_MOVE); - } - } - return rc; -} - -/* - * Minimizes or Iconifies a top-level window. - * Parameters: - * handle: The window handle to minimize. - */ -int API dw_window_minimize(HWND handle) -{ - HWND hwndclient = WinWindowFromID(handle, FID_CLIENT); - - if(hwndclient) - { - Box *box = (Box *)WinQueryWindowPtr(hwndclient, QWP_USER); - - if(box) - { - if(!box->titlebar && box->hwndtitle) - WinSetParent(box->hwndtitle, handle, FALSE); - } - } - - return WinSetWindowPos(handle, NULLHANDLE, 0, 0, 0, 0, SWP_MINIMIZE); -} - -/* - * Makes the window invisible. - * Parameters: - * handle: The window handle to make visible. - */ -int API dw_window_hide(HWND handle) -{ - HSWITCH hswitch; - SWCNTRL swcntrl; - - /* If this window has a switch list entry make sure it is invisible */ - hswitch = WinQuerySwitchHandle(handle, 0); - if(hswitch) - { - WinQuerySwitchEntry(hswitch, &swcntrl); - swcntrl.uchVisibility = SWL_INVISIBLE; - WinChangeSwitchEntry(hswitch, &swcntrl); - } - return WinShowWindow(handle, FALSE); -} - -/* - * Destroys a window and all of it's children. - * Parameters: - * handle: The window handle to destroy. - */ -int API dw_window_destroy(HWND handle) -{ - HWND frame, menu, parent = WinQueryWindow(handle, QW_PARENT); - Box *thisbox = WinQueryWindowPtr(parent, QWP_USER); - - if(!handle) - return -1; - - frame = (HWND)dw_window_get_data(handle, "_dw_combo_box"); - - if((menu = WinWindowFromID(handle, FID_MENU)) != NULLHANDLE) - _free_menu_data(menu); - - if(parent != desktop && thisbox && thisbox->count) - { - int z, index = -1; - Item *tmpitem, *thisitem = thisbox->items; - - for(z=0;z<thisbox->count;z++) - { - if(thisitem[z].hwnd == handle) - index = z; - } - - if(index == -1) - return 0; - - tmpitem = malloc(sizeof(Item)*(thisbox->count-1)); - - /* Copy all but the current entry to the new list */ - for(z=0;z<index;z++) - { - tmpitem[z] = thisitem[z]; - } - for(z=index+1;z<thisbox->count;z++) - { - tmpitem[z-1] = thisitem[z]; - } - - thisbox->items = tmpitem; - free(thisitem); - thisbox->count--; - _free_window_memory(frame ? frame : handle); - } - return WinDestroyWindow(frame ? frame : handle); -} - -/* Causes entire window to be invalidated and redrawn. - * Parameters: - * handle: Toplevel window handle to be redrawn. - */ -void API dw_window_redraw(HWND handle) -{ - HWND client = WinWindowFromID(handle, FID_CLIENT); - HWND window = client ? client : handle; - Box *mybox = (Box *)WinQueryWindowPtr(window, QWP_USER); - - if(window && mybox) - { - unsigned long width, height; - - dw_window_get_pos_size(window, NULL, NULL, &width, &height); - - WinShowWindow(client ? mybox->items[0].hwnd : handle, FALSE); - _do_resize(mybox, width, height); - WinShowWindow(client ? mybox->items[0].hwnd : handle, TRUE); - } -} - -/* - * Changes a window's parent to newparent. - * Parameters: - * handle: The window handle to destroy. - * newparent: The window's new parent window. - */ -void API dw_window_reparent(HWND handle, HWND newparent) -{ - HWND blah = WinWindowFromID(newparent, FID_CLIENT); - WinSetParent(handle, blah ? blah : newparent, TRUE); -} - -/* - * Sets the font used by a specified window (widget) handle. - * Parameters: - * handle: The window (widget) handle. - * fontname: Name and size of the font in the form "size.fontname" - */ -int API dw_window_set_font(HWND handle, char *fontname) -{ - return WinSetPresParam(handle, PP_FONTNAMESIZE, strlen(fontname)+1, fontname); -} - -/* Internal version */ -int _dw_window_set_color(HWND handle, ULONG fore, ULONG back) -{ - if((fore & DW_RGB_COLOR) == DW_RGB_COLOR) - { - RGB2 rgb2; - - rgb2.bBlue = DW_BLUE_VALUE(fore); - rgb2.bGreen = DW_GREEN_VALUE(fore); - rgb2.bRed = DW_RED_VALUE(fore); - rgb2.fcOptions = 0; - - WinSetPresParam(handle, PP_FOREGROUNDCOLOR, sizeof(RGB2), &rgb2); - - } - else if(fore != DW_CLR_DEFAULT) - { - fore = _internal_color(fore); - - WinSetPresParam(handle, PP_FOREGROUNDCOLORINDEX, sizeof(ULONG), &fore); - } - if((back & DW_RGB_COLOR) == DW_RGB_COLOR) - { - RGB2 rgb2; - - rgb2.bBlue = DW_BLUE_VALUE(back); - rgb2.bGreen = DW_GREEN_VALUE(back); - rgb2.bRed = DW_RED_VALUE(back); - rgb2.fcOptions = 0; - - WinSetPresParam(handle, PP_BACKGROUNDCOLOR, sizeof(RGB2), &rgb2); - return 0; - } - else if(back != DW_CLR_DEFAULT) - { - back = _internal_color(back); - - WinSetPresParam(handle, PP_BACKGROUNDCOLORINDEX, sizeof(ULONG), &back); - } - return 0; -} -/* - * Sets the colors used by a specified window (widget) handle. - * Parameters: - * handle: The window (widget) handle. - * fore: Foreground color in DW_RGB format or a default color index. - * back: Background color in DW_RGB format or a default color index. - */ -int API dw_window_set_color(HWND handle, ULONG fore, ULONG back) -{ - dw_window_set_data(handle, "_dw_fore", (void *)(fore+1)); - dw_window_set_data(handle, "_dw_back", (void *)(back+1)); - - return _dw_window_set_color(handle, fore, back); -} - -/* - * Sets the font used by a specified window (widget) handle. - * Parameters: - * handle: The window (widget) handle. - * border: Size of the window border in pixels. - */ -int API dw_window_set_border(HWND handle, int border) -{ - WinSendMsg(handle, WM_SETBORDERSIZE, MPFROMSHORT(border), MPFROMSHORT(border)); - return 0; -} - -/* - * Captures the mouse input to this window. - * Parameters: - * handle: Handle to receive mouse input. - */ -void API dw_window_capture(HWND handle) -{ - WinSetCapture(HWND_DESKTOP, handle); -} - -/* - * Releases previous mouse capture. - */ -void API dw_window_release(void) -{ - WinSetCapture(HWND_DESKTOP, NULLHANDLE); -} - -/* - * Tracks this window movement. - * Parameters: - * handle: Handle to frame to be tracked. - */ -void API dw_window_track(HWND handle) -{ - WinSendMsg(handle, WM_TRACKFRAME, MPFROMSHORT(TF_MOVE), 0); -} - -/* - * Changes the appearance of the mouse pointer. - * Parameters: - * handle: Handle to widget for which to change. - * cursortype: ID of the pointer you want. - */ -void API dw_window_pointer(HWND handle, int pointertype) -{ - if(handle == HWND_DESKTOP) - WinSetPointer(handle, WinQuerySysPointer(HWND_DESKTOP,pointertype, FALSE)); - else - dw_window_set_data(handle, "_dw_pointer", - pointertype < 65535 ? - (void *)WinQuerySysPointer(HWND_DESKTOP,pointertype, FALSE) - : (void *)pointertype); -} - -/* - * Create a new Window Frame. - * Parameters: - * owner: The Owner's window handle or HWND_DESKTOP. - * title: The Window title. - * flStyle: Style flags, see the PM reference. - */ -HWND API dw_window_new(HWND hwndOwner, char *title, ULONG flStyle) -{ - HWND hwndclient = 0, hwndframe; - Box *newbox = calloc(1, sizeof(Box)); - WindowData *blah = calloc(1, sizeof(WindowData)); - ULONG winStyle = 0L; - - newbox->pad = 0; - newbox->type = DW_VERT; - newbox->count = 0; - - flStyle |= FCF_NOBYTEALIGN; - - if(flStyle & DW_FCF_TITLEBAR) - newbox->titlebar = 1; - else - flStyle |= FCF_TITLEBAR; - - if(!(flStyle & FCF_SHELLPOSITION)) - blah->flags |= DW_OS2_NEW_WINDOW; - - if(flStyle & WS_MAXIMIZED) - { - winStyle |= WS_MAXIMIZED; - flStyle &= ~WS_MAXIMIZED; - } - if(flStyle & WS_MINIMIZED) - { - winStyle |= WS_MINIMIZED; - flStyle &= ~WS_MINIMIZED; - } - - hwndframe = WinCreateStdWindow(hwndOwner, winStyle, &flStyle, ClassName, title, 0L, NULLHANDLE, 0L, &hwndclient); - newbox->hwndtitle = WinWindowFromID(hwndframe, FID_TITLEBAR); - if(!newbox->titlebar && newbox->hwndtitle) - WinSetParent(newbox->hwndtitle, HWND_OBJECT, FALSE); - blah->oldproc = WinSubclassWindow(hwndframe, _sizeproc); - WinSetWindowPtr(hwndframe, QWP_USER, blah); - WinSetWindowPtr(hwndclient, QWP_USER, newbox); - - return hwndframe; -} - -/* - * Create a new Box to be packed. - * Parameters: - * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). - * pad: Number of pixels to pad around the box. - */ -HWND API dw_box_new(int type, int pad) -{ - Box *newbox = calloc(1, sizeof(Box)); - HWND hwndframe; - - newbox->pad = pad; - newbox->type = type; - newbox->count = 0; - newbox->grouphwnd = NULLHANDLE; - - hwndframe = WinCreateWindow(HWND_OBJECT, - WC_FRAME, - NULL, - WS_VISIBLE | WS_CLIPCHILDREN | - FS_NOBYTEALIGN, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - 0L, - NULL, - NULL); - - newbox->oldproc = WinSubclassWindow(hwndframe, _controlproc); - WinSetWindowPtr(hwndframe, QWP_USER, newbox); - dw_window_set_color(hwndframe, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY); - return hwndframe; -} - -/* - * Create a new Group Box to be packed. - * Parameters: - * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). - * pad: Number of pixels to pad around the box. - * title: Text to be displayined in the group outline. - */ -HWND API dw_groupbox_new(int type, int pad, char *title) -{ - Box *newbox = calloc(1, sizeof(Box)); - HWND hwndframe; - - newbox->pad = pad; - newbox->type = type; - newbox->count = 0; - - hwndframe = WinCreateWindow(HWND_OBJECT, - WC_FRAME, - NULL, - WS_VISIBLE | - FS_NOBYTEALIGN, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - 0L, - NULL, - NULL); - - newbox->grouphwnd = WinCreateWindow(hwndframe, - WC_STATIC, - title, - WS_VISIBLE | SS_GROUPBOX | - WS_GROUP, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - 0L, - NULL, - NULL); - - WinSetWindowPtr(hwndframe, QWP_USER, newbox); - dw_window_set_color(hwndframe, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY); - dw_window_set_color(newbox->grouphwnd, DW_CLR_BLACK, DW_CLR_PALEGRAY); - dw_window_set_font(newbox->grouphwnd, DefaultFont); - return hwndframe; -} - -/* - * Create a new MDI Frame to be packed. - * Parameters: - * id: An ID to be used with dw_window_from_id or 0L. - */ -HWND API dw_mdi_new(unsigned long id) -{ - HWND hwndframe; - - id = id; /* keep compiler happy */ - hwndframe = WinCreateWindow(HWND_OBJECT, - WC_FRAME, - NULL, - WS_VISIBLE | WS_CLIPCHILDREN | - FS_NOBYTEALIGN, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - 0L, - NULL, - NULL); - return hwndframe; -} - -/* - * Create a bitmap object to be packed. - * Parameters: - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_bitmap_new(ULONG id) -{ - return WinCreateWindow(HWND_OBJECT, - WC_STATIC, - NULL, - WS_VISIBLE | SS_TEXT, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); -} - -/* - * Create a notebook object to be packed. - * Parameters: - * id: An ID to be used for getting the resource from the - * resource file. - */ -HWND API dw_notebook_new(ULONG id, int top) -{ - ULONG flags; - HWND tmp; - - if(top) - flags = BKS_MAJORTABTOP; - else - flags = BKS_MAJORTABBOTTOM; - - tmp = WinCreateWindow(HWND_OBJECT, - WC_NOTEBOOK, - NULL, - WS_VISIBLE | -#ifdef BKS_TABBEDDIALOG - BKS_TABBEDDIALOG | -#endif - flags, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - - /* Fix tab sizes on Warp 3 */ - if(!IS_WARP4()) - { - /* best sizes to be determined by trial and error */ - WinSendMsg(tmp, BKM_SETDIMENSIONS,MPFROM2SHORT(102, 28), MPFROMSHORT( BKA_MAJORTAB)); - } - - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Create a menu object to be popped up. - * Parameters: - * id: An ID to be used for getting the resource from the - * resource file. - */ -HMENUI API dw_menu_new(ULONG id) -{ - HMENUI tmp = WinCreateWindow(HWND_OBJECT, - WC_MENU, - NULL, - WS_VISIBLE, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - return tmp; -} - -/* - * Create a menubar on a window. - * Parameters: - * location: Handle of a window frame to be attached to. - */ -HMENUI API dw_menubar_new(HWND location) -{ - HMENUI tmp = WinCreateWindow(location, - WC_MENU, - NULL, - WS_VISIBLE | MS_ACTIONBAR, - 0,0,2000,1000, - location, - HWND_TOP, - FID_MENU, - NULL, - NULL); - dw_window_set_data(tmp, "_dw_owner", (void *)location); - dw_window_set_data(tmp, "_dw_menubar", (void *)location); - return tmp; -} - -/* - * Destroys a menu created with dw_menubar_new or dw_menu_new. - * Parameters: - * menu: Handle of a menu. - */ -void API dw_menu_destroy(HMENUI *menu) -{ - if(menu) - WinDestroyWindow(*menu); -} - -/* - * Adds a menuitem or submenu to an existing menu. - * Parameters: - * menu: The handle the the existing menu. - * title: The title text on the menu item to be added. - * id: An ID to be used for message passing. - * flags: Extended attributes to set on the menu. - * end: If TRUE memu is positioned at the end of the menu. - * check: If TRUE menu is "check"able. - * submenu: Handle to an existing menu to be a submenu or NULL. - */ -HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu) -{ - MENUITEM miSubMenu; - char buffer[15]; - - check = check; /* keep compiler happy */ - if(!menux || id > 65536) - return NULLHANDLE; - - if(end) - miSubMenu.iPosition=MIT_END; - else - miSubMenu.iPosition=0; - - if(strlen(title) == 0) - miSubMenu.afStyle=MIS_SEPARATOR | flags; - else - miSubMenu.afStyle=MIS_TEXT | flags; - miSubMenu.afAttribute=0; - miSubMenu.id=id; - miSubMenu.hwndSubMenu = submenu; - miSubMenu.hItem=NULLHANDLE; - - WinSendMsg(menux, - MM_INSERTITEM, - MPFROMP(&miSubMenu), - MPFROMP(title)); - - sprintf(buffer, "_dw_id%d", id); - dw_window_set_data(hwndApp, buffer, (void *)menux); - - if(submenu) - dw_window_set_data(submenu, "_dw_owner", (void *)menux); - return (HWND)id; -} - -/* - * Sets the state of a menu item check. - * Parameters: - * menu: The handle the the existing menu. - * id: Menuitem id. - * check: TRUE for checked FALSE for not checked. - */ -void API dw_menu_item_set_check(HMENUI menux, unsigned long id, int check) -{ - if(check) - WinSendMsg(menux, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE), - MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)); - else - WinSendMsg(menux, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE), - MPFROM2SHORT(MIA_CHECKED, 0)); -} - -/* - * Pops up a context menu at given x and y coordinates. - * Parameters: - * menu: The handle the the existing menu. - * parent: Handle to the window initiating the popup. - * x: X coordinate. - * y: Y coordinate. - */ -void API dw_menu_popup(HMENUI *menu, HWND parent, int x, int y) -{ - if(menu) - { - popup = parent; - WinPopupMenu(HWND_DESKTOP, parent, *menu, x, dw_screen_height() - y, 0, PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_VCONSTRAIN | PU_HCONSTRAIN); - } -} - -/* - * Returns the current X and Y coordinates of the mouse pointer. - * Parameters: - * x: Pointer to variable to store X coordinate. - * y: Pointer to variable to store Y coordinate. - */ -void API dw_pointer_query_pos(long *x, long *y) -{ - POINTL ptl; - - WinQueryPointerPos(HWND_DESKTOP, &ptl); - if(x && y) - { - *x = ptl.x; - *y = dw_screen_height() - ptl.y; - } -} - -/* - * Sets the X and Y coordinates of the mouse pointer. - * Parameters: - * x: X coordinate. - * y: Y coordinate. - */ -void API dw_pointer_set_pos(long x, long y) -{ - WinSetPointerPos(HWND_DESKTOP, x, dw_screen_height() - y); -} - - -/* - * Create a container object to be packed. - * Parameters: - * id: An ID to be used for getting the resource from the - * resource file. - */ -HWND API dw_container_new(ULONG id, int multi) -{ - WindowData *blah = calloc(1, sizeof(WindowData)); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_CONTAINER, - NULL, - WS_VISIBLE | CCS_READONLY | - (multi ? CCS_EXTENDSEL : CCS_SINGLESEL) | - CCS_AUTOPOSITION, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - blah->oldproc = WinSubclassWindow(tmp, _TreeProc); - WinSetWindowPtr(tmp, QWP_USER, blah); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_data(tmp, "_dw_container", (void *)1); - return tmp; -} - -/* - * Create a tree object to be packed. - * Parameters: - * id: An ID to be used for getting the resource from the - * resource file. - */ -HWND API dw_tree_new(ULONG id) -{ - CNRINFO cnrinfo; - WindowData *blah = calloc(1, sizeof(WindowData)); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_CONTAINER, - NULL, - WS_VISIBLE | CCS_READONLY | - CCS_SINGLESEL | CCS_AUTOPOSITION, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - - cnrinfo.flWindowAttr = CV_TREE | CA_TREELINE; - cnrinfo.slBitmapOrIcon.cx = 16; - cnrinfo.slBitmapOrIcon.cy = 16; - cnrinfo.cyLineSpacing = 0; - cnrinfo.cxTreeIndent = 16; - cnrinfo.cxTreeLine = 1; - - WinSendMsg(tmp, CM_SETCNRINFO, &cnrinfo, MPFROMLONG(CMA_FLWINDOWATTR | CMA_SLBITMAPORICON | - CMA_LINESPACING | CMA_CXTREEINDENT | CMA_CXTREELINE)); - blah->oldproc = WinSubclassWindow(tmp, _TreeProc); - WinSetWindowPtr(tmp, QWP_USER, blah); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Create a new static text window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_text_new(char *text, ULONG id) -{ - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_STATIC, - text, - WS_VISIBLE | SS_TEXT, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); - return tmp; -} - -/* - * Create a new status text window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_status_text_new(char *text, ULONG id) -{ - WindowData *blah = calloc(sizeof(WindowData), 1); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_STATIC, - text, - WS_VISIBLE | SS_TEXT, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - blah->oldproc = WinSubclassWindow(tmp, _statusproc); - WinSetWindowPtr(tmp, QWP_USER, blah); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); - return tmp; -} - -#ifndef MLS_LIMITVSCROLL -#define MLS_LIMITVSCROLL 0x00000080L -#endif - -/* - * Create a new Multiline Editbox window (widget) to be packed. - * Parameters: - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_mle_new(ULONG id) -{ - WindowData *blah = calloc(1, sizeof(WindowData)); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_MLE, - "", - WS_VISIBLE | - MLS_BORDER | MLS_IGNORETAB | - MLS_READONLY | MLS_VSCROLL | - MLS_LIMITVSCROLL, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - blah->oldproc = WinSubclassWindow(tmp, _mleproc); - WinSetWindowPtr(tmp, QWP_USER, blah); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Create a new Entryfield window (widget) to be packed. - * Parameters: - * text: The default text to be in the entryfield widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_entryfield_new(char *text, ULONG id) -{ - - WindowData *blah = calloc(1, sizeof(WindowData)); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_ENTRYFIELD, - text, - WS_VISIBLE | ES_MARGIN | - ES_AUTOSCROLL | WS_TABSTOP, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - blah->oldproc = WinSubclassWindow(tmp, _entryproc); - WinSetWindowPtr(tmp, QWP_USER, blah); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE); - return tmp; -} - -/* - * Create a new Entryfield (password) window (widget) to be packed. - * Parameters: - * text: The default text to be in the entryfield widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_entryfield_password_new(char *text, ULONG id) -{ - WindowData *blah = calloc(1, sizeof(WindowData)); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_ENTRYFIELD, - text, - WS_VISIBLE | ES_MARGIN | ES_UNREADABLE | - ES_AUTOSCROLL | WS_TABSTOP, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - blah->oldproc = WinSubclassWindow(tmp, _entryproc); - WinSetWindowPtr(tmp, QWP_USER, blah); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE); - return tmp; -} - -/* - * Create a new Combobox window (widget) to be packed. - * Parameters: - * text: The default text to be in the combpbox widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_combobox_new(char *text, ULONG id) -{ - WindowData *blah = calloc(1, sizeof(WindowData)); - HWND frame = dw_box_new(DW_HORZ, 0); - HWND tmp = WinCreateWindow(frame, - WC_COMBOBOX, - text, - WS_VISIBLE | CBS_DROPDOWN | WS_GROUP, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - HENUM henum = WinBeginEnumWindows(tmp); - HWND child, last = NULLHANDLE; - - while((child = WinGetNextWindow(henum)) != NULLHANDLE) - { - WindowData *moreblah = calloc(1, sizeof(WindowData)); - moreblah->oldproc = WinSubclassWindow(child, _comboentryproc); - WinSetWindowPtr(child, QWP_USER, moreblah); - dw_window_set_color(child, DW_CLR_BLACK, DW_CLR_WHITE); - last = child; - } - WinEndEnumWindows(henum); - blah->oldproc = WinSubclassWindow(tmp, _comboproc); - WinSetWindowPtr(tmp, QWP_USER, blah); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE); - dw_window_set_data(tmp, "_dw_comboentry", (void *)last); - dw_window_set_data(tmp, "_dw_combo_box", (void *)frame); - WinSetOwner(tmp, frame); - return tmp; -} - -/* - * Create a new button window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_button_new(char *text, ULONG id) -{ - BubbleButton *bubble = calloc(sizeof(BubbleButton), 1); - - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_BUTTON, - text, - WS_VISIBLE, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - - bubble->id = id; - bubble->bubbletext[0] = '\0'; - bubble->pOldProc = WinSubclassWindow(tmp, _BtProc); - - WinSetWindowPtr(tmp, QWP_USER, bubble); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); - return tmp; -} - -/* Function: GenResIDStr -** Abstract: Generate string '#nnnn' for a given ID for using with Button -** controls -*/ - -void _GenResIDStr(CHAR *buff, ULONG ulID) -{ - char *str; - int slen = 0; - - *buff++ = '#'; - - str = buff; - - do - { - *str++ = (ulID % 10) + '0'; - ulID /= 10; - slen++; - } - while(ulID); - - *str-- = 0; - - for(; str > buff; str--, buff++) - { - *buff ^= *str; - *str ^= *buff; - *buff ^= *str; - } -} - - -/* - * Create a new bitmap button window (widget) to be packed. - * Parameters: - * text: Bubble help text to be displayed. - * id: An ID of a bitmap in the resource file. - */ -HWND API dw_bitmapbutton_new(char *text, ULONG id) -{ - char idbuf[256]; - HWND tmp; - BubbleButton *bubble = calloc(sizeof(BubbleButton), 1); - - _GenResIDStr(idbuf, id); - - tmp = WinCreateWindow(HWND_OBJECT, - WC_BUTTON, - idbuf, - WS_VISIBLE | BS_PUSHBUTTON | - BS_BITMAP | BS_AUTOSIZE | - BS_NOPOINTERFOCUS, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - - bubble->id = id; - strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1); - bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0'; - bubble->pOldProc = WinSubclassWindow(tmp, _BtProc); - - WinSetWindowPtr(tmp, QWP_USER, bubble); - dw_window_set_data(tmp, "_dw_bitmapbutton", (void *)1); - return tmp; -} - -/* - * Create a new bitmap button window (widget) to be packed from a file. - * Parameters: - * text: Bubble help text to be displayed. - * id: An ID to be used with dw_window_from_id() or 0L. - * filename: Name of the file, omit extention to have - * DW pick the appropriate file extension. - * (BMP on OS/2 or Windows, XPM on Unix) - */ -HWND dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename) -{ - BubbleButton *bubble = calloc(sizeof(BubbleButton), 1); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_BUTTON, - "", - WS_VISIBLE | BS_PUSHBUTTON | - BS_AUTOSIZE | BS_NOPOINTERFOCUS, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - char *file = alloca(strlen(filename) + 5); - HPIXMAP pixmap = NULL, disabled = NULL; - - if(file && (pixmap = calloc(1,sizeof(struct _hpixmap)))) - { - int z, j, lim; - LONG fore; - - strcpy(file, filename); - - /* check if we can read from this file (it exists and read permission) */ - if(access(file, 04) != 0) - { - /* Try with .bmp extention */ - strcat(file, ".bmp"); - if(access(file, 04) != 0) - { -#if 0 /* don't free pixmap if bitmap doesn't exist; causes crash several lines below */ - free(pixmap); - pixmap = NULL; -#endif - } - } - - /* Try to load the bitmap from file */ - if(pixmap) - _load_bitmap_file(file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height); - - /* Create a disabled style pixmap */ - disabled = dw_pixmap_new(tmp, pixmap->width, pixmap->height, dw_color_depth()); - 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; - } - - bubble->id = id; - strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1); - bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0'; - bubble->pOldProc = WinSubclassWindow(tmp, _BtProc); - - WinSetWindowPtr(tmp, QWP_USER, bubble); - - dw_window_set_data(tmp, "_dw_hpixmap", (void *)pixmap); - dw_window_set_data(tmp, "_dw_hpixmap_disabled", (void *)disabled); - dw_window_set_data(tmp, "_dw_bitmapbutton", (void *)1); - return tmp; -} - -/* - * Create a new spinbutton window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_spinbutton_new(char *text, ULONG id) -{ - WindowData *blah = calloc(sizeof(WindowData), 1); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_SPINBUTTON, - text, - WS_VISIBLE | SPBS_MASTER, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - HWND entry = _find_entryfield(tmp); - blah->oldproc = WinSubclassWindow(tmp, _entryproc); - WinSetWindowPtr(tmp, QWP_USER, blah); - blah = calloc(sizeof(WindowData), 1); - blah->oldproc = WinSubclassWindow(entry, _spinentryproc); - WinSetWindowPtr(entry, QWP_USER, blah); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_color(entry, DW_CLR_BLACK, DW_CLR_WHITE); - return tmp; -} - -/* - * Create a new radiobutton window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_radiobutton_new(char *text, ULONG id) -{ - WindowData *blah = calloc(sizeof(WindowData), 1); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_BUTTON, - text, - WS_VISIBLE | - BS_AUTORADIOBUTTON, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - blah->oldproc = WinSubclassWindow(tmp, _entryproc); - WinSetWindowPtr(tmp, QWP_USER, blah); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); - return tmp; -} - - -/* - * Create a new slider window (widget) to be packed. - * Parameters: - * vertical: TRUE or FALSE if slider is vertical. - * increments: Number of increments available. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_slider_new(int vertical, int increments, ULONG id) -{ - WindowData *blah = calloc(1, sizeof(WindowData)); - SLDCDATA sldcData = { 0, 0, 0, 0, 0 }; - HWND tmp; - - sldcData.cbSize = sizeof(SLDCDATA); - sldcData.usScale1Increments = increments; - - tmp = WinCreateWindow(HWND_OBJECT, - WC_SLIDER, - "", - WS_VISIBLE | SLS_SNAPTOINCREMENT | - (vertical ? SLS_VERTICAL : SLS_HORIZONTAL), - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - &sldcData, - NULL); - - blah->oldproc = WinSubclassWindow(tmp, _entryproc); - WinSetWindowPtr(tmp, QWP_USER, blah); - return tmp; -} - -/* - * Create a new scrollbar window (widget) to be packed. - * Parameters: - * vertical: TRUE or FALSE if scrollbar is vertical. - * increments: Number of increments available. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_scrollbar_new(int vertical, int increments, ULONG id) -{ - increments = increments; /* keep compiler happy */ - return WinCreateWindow(HWND_OBJECT, - WC_SCROLLBAR, - "", - WS_VISIBLE | SBS_AUTOTRACK | - (vertical ? SBS_VERT : SBS_HORZ), - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); -} - -/* - * Create a new percent bar window (widget) to be packed. - * Parameters: - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_percent_new(ULONG id) -{ - WindowData *blah = calloc(1, sizeof(WindowData)); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_SLIDER, - "", - WS_VISIBLE | SLS_READONLY - | SLS_RIBBONSTRIP, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - blah->oldproc = WinSubclassWindow(tmp, _percentproc); - WinSetWindowPtr(tmp, QWP_USER, blah); - dw_window_disable(tmp); - return tmp; -} - -/* - * Create a new checkbox window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_checkbox_new(char *text, ULONG id) -{ - BubbleButton *bubble = calloc(sizeof(BubbleButton), 1); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_BUTTON, - text, - WS_VISIBLE | BS_AUTOCHECKBOX, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - bubble->id = id; - bubble->bubbletext[0] = '\0'; - bubble->pOldProc = WinSubclassWindow(tmp, _BtProc); - WinSetWindowPtr(tmp, QWP_USER, bubble); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); - return tmp; -} - -/* - * Create a new listbox window (widget) to be packed. - * Parameters: - * id: An ID to be used with dw_window_from_id() or 0L. - * multi: Multiple select TRUE or FALSE. - */ -HWND API dw_listbox_new(ULONG id, int multi) -{ - WindowData *blah = calloc(sizeof(WindowData), 1); - HWND tmp = WinCreateWindow(HWND_OBJECT, - WC_LISTBOX, - NULL, - WS_VISIBLE | LS_NOADJUSTPOS | - (multi ? LS_MULTIPLESEL : 0), - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - blah->oldproc = WinSubclassWindow(tmp, _entryproc); - WinSetWindowPtr(tmp, QWP_USER, blah); - dw_window_set_font(tmp, DefaultFont); - dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE); - return tmp; -} - -/* - * Sets the icon used for a given window. - * Parameters: - * handle: Handle to the window. - * id: An ID to be used to specify the icon. - */ -void API dw_window_set_icon(HWND handle, ULONG id) -{ - HPOINTER icon = id < 65536 ? WinLoadPointer(HWND_DESKTOP,NULLHANDLE,id) : (HPOINTER)id; - WinSendMsg(handle, WM_SETICON, (MPARAM)icon, 0); -} - -/* 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) -{ - HFILE BitmapFileHandle = NULLHANDLE; /* handle for the file */ - ULONG OpenAction = 0; - PBYTE BitmapFileBegin; /* pointer to the first byte of bitmap data */ - FILESTATUS BitmapStatus; - ULONG cbRead; - PBITMAPFILEHEADER2 pBitmapFileHeader; - PBITMAPINFOHEADER2 pBitmapInfoHeader; - ULONG ScanLines, ulFlags; - HPS hps1; - HDC hdc1; - SIZEL sizl = { 0, 0 }; - - /* open bitmap file */ - DosOpen(file, &BitmapFileHandle, &OpenAction, 0L, - FILE_ARCHIVED | FILE_NORMAL | FILE_READONLY, - OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, - OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY | - OPEN_FLAGS_NOINHERIT, 0L); - - if(!BitmapFileHandle) - return 0; - - /* find out how big the file is */ - DosQueryFileInfo(BitmapFileHandle, 1, &BitmapStatus, - sizeof(BitmapStatus)); - - /* allocate memory to load the bitmap */ - DosAllocMem((PPVOID)&BitmapFileBegin, (ULONG)BitmapStatus.cbFile, - PAG_READ | PAG_WRITE | PAG_COMMIT); - - /* read bitmap file into memory buffer */ - DosRead(BitmapFileHandle, (PVOID)BitmapFileBegin, - BitmapStatus.cbFile, &cbRead); - - /* access first bytes as bitmap header */ - pBitmapFileHeader = (PBITMAPFILEHEADER2)BitmapFileBegin; - - /* check if it's a valid bitmap data file */ - if((pBitmapFileHeader->usType != BFT_BITMAPARRAY) && - (pBitmapFileHeader->usType != BFT_BMAP)) - { - /* free memory of bitmap file buffer */ - DosFreeMem(BitmapFileBegin); - /* close the bitmap file */ - DosClose(BitmapFileHandle); - return 0; - } - - /* check if it's a file with multiple bitmaps */ - if(pBitmapFileHeader->usType == BFT_BITMAPARRAY) - { - /* we'll just use the first bitmap and ignore the others */ - pBitmapFileHeader = &(((PBITMAPARRAYFILEHEADER2)BitmapFileBegin)->bfh2); - } - - /* set pointer to bitmap information block */ - pBitmapInfoHeader = &pBitmapFileHeader->bmp2; - - /* find out if it's the new 2.0 format or the old format */ - /* and query number of lines */ - if(pBitmapInfoHeader->cbFix == sizeof(BITMAPINFOHEADER)) - { - *height = ScanLines = (ULONG)((PBITMAPINFOHEADER)pBitmapInfoHeader)->cy; - *width = (ULONG)((PBITMAPINFOHEADER)pBitmapInfoHeader)->cx; - } - else - { - *height = ScanLines = pBitmapInfoHeader->cy; - *width = pBitmapInfoHeader->cx; - } - - /* now we need a presentation space, get it from static control */ - hps1 = WinGetPS(handle); - - hdc1 = GpiQueryDevice(hps1); - ulFlags = GpiQueryPS(hps1, &sizl); - - *hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc1); - *hps = GpiCreatePS (dwhab, *hdc, &sizl, ulFlags | GPIA_ASSOC); - - /* create bitmap now using the parameters from the info block */ - *hbm = GpiCreateBitmap(*hps, pBitmapInfoHeader, 0L, NULL, NULL); - - /* select the new bitmap into presentation space */ - GpiSetBitmap(*hps, *hbm); - - /* now copy the bitmap data into the bitmap */ - GpiSetBitmapBits(*hps, 0L, ScanLines, - BitmapFileBegin + pBitmapFileHeader->offBits, - (PBITMAPINFO2)pBitmapInfoHeader); - - WinReleasePS(hps1); - - /* free memory of bitmap file buffer */ - DosFreeMem(BitmapFileBegin); - /* close the bitmap file */ - DosClose(BitmapFileHandle); - return 1; -} - -/* - * Sets the bitmap used for a given static window. - * Parameters: - * handle: Handle to the window. - * id: An ID to be used to specify the icon, - * (pass 0 if you use the filename param) - * filename: a path to a file (Bitmap on OS/2 or - * Windows and a pixmap on Unix, pass - * NULL if you use the id param) - */ -void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename) -{ - HBITMAP hbm; - HPS hps; - - /* Destroy any old bitmap data */ - _free_bitmap(handle); - - /* If id is non-zero use the resource */ - if(id) - { - hps = WinGetPS(handle); - - hbm = GpiLoadBitmap(hps, NULLHANDLE, id, 0, 0); - } - else if(filename) - { - HDC hdc; - unsigned long width, height; - char *file = alloca(strlen(filename) + 5); - - if(!file) - return; - - strcpy(file, filename); - - /* check if we can read from this file (it exists and read permission) */ - if(access(file, 04) != 0) - { - /* Try with .bmp extention */ - strcat(file, ".bmp"); - if(access(file, 04) != 0) - return; - } - - if(!_load_bitmap_file(file, handle, &hbm, &hdc, &hps, &width, &height)) - return; - - dw_window_set_data(handle, "_dw_hps", (void *)hps); - dw_window_set_data(handle, "_dw_hdc", (void *)hdc); - dw_window_set_data(handle, "_dw_width", (void *)width); - dw_window_set_data(handle, "_dw_height", (void *)height); - } - else - return; - - WinSetWindowBits(handle,QWL_STYLE,SS_BITMAP,SS_BITMAP | 0x7f); - WinSendMsg( handle, SM_SETHANDLE, MPFROMP(hbm), NULL ); - if(id) - WinReleasePS(hps); - dw_window_set_data(handle, "_dw_bitmap", (void *)hbm); -} - -/* - * Sets the text used for a given window. - * Parameters: - * handle: Handle to the window. - * text: The text associsated with a given window. - */ -void API dw_window_set_text(HWND handle, char *text) -{ - WinSetWindowText(handle, text); -} - -/* - * Gets the text used for a given window. - * Parameters: - * handle: Handle to the window. - * Returns: - * text: The text associsated with a given window. - */ -char * API dw_window_get_text(HWND handle) -{ - int len = WinQueryWindowTextLength(handle); - char *tempbuf = calloc(1, len + 2); - - WinQueryWindowText(handle, len + 1, tempbuf); - - return tempbuf; -} - -/* - * Disables given window (widget). - * Parameters: - * handle: Handle to the window. - */ -void API dw_window_disable(HWND handle) -{ - char tmpbuf[100]; - - if(dw_window_get_data(handle, "_dw_disabled")) - return; - - WinQueryClassName(handle, 99, tmpbuf); - dw_window_set_data(handle, "_dw_disabled", (void *)1); - - if(tmpbuf[0] == '#') - { - int val = atoi(&tmpbuf[1]); - HWND hwnd; - - switch(val) - { - case 2: - case 6: - case 10: - case 32: - case 7: - hwnd = _find_entryfield(handle); - _dw_window_set_color(hwnd ? hwnd : handle, DW_CLR_BLACK, DW_CLR_PALEGRAY); - dw_signal_connect(hwnd ? hwnd : handle, DW_SIGNAL_KEY_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100); - if(val == 2) - dw_signal_connect(handle, DW_SIGNAL_BUTTON_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100); - if(hwnd) - dw_window_set_data(hwnd, "_dw_disabled", (void *)1); - return; - case 3: - if(dw_window_get_data(handle, "_dw_bitmapbutton") && !dw_window_get_data(handle, "_dw_hpixmap")) - WinEnableWindow(handle, FALSE); - else if(dw_window_get_data(handle, "_dw_bitmapbutton") && dw_window_get_data(handle, "_dw_hpixmap_disabled")) - WinInvalidateRect(handle, NULL, FALSE); - else - _dw_window_set_color(handle, DW_CLR_DARKGRAY, DW_CLR_PALEGRAY); - dw_signal_connect(handle, DW_SIGNAL_KEY_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100); - dw_signal_connect(handle, DW_SIGNAL_BUTTON_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100); - return; - } - } - WinEnableWindow(handle, FALSE); -} - -/* - * Enables given window (widget). - * Parameters: - * handle: Handle to the window. - */ -void API dw_window_enable(HWND handle) -{ - ULONG fore = (ULONG)dw_window_get_data(handle, "_dw_fore"); - ULONG back = (ULONG)dw_window_get_data(handle, "_dw_back"); - HWND hwnd = _find_entryfield(handle); - - dw_window_set_data(handle, "_dw_disabled", 0); - if(hwnd) - dw_window_set_data(hwnd, "_dw_disabled", 0); - if(fore && back) - _dw_window_set_color(hwnd ? hwnd : handle, fore-1, back-1); - dw_signal_disconnect_by_data(handle, (void *)100); - WinEnableWindow(handle, TRUE); - if(dw_window_get_data(handle, "_dw_bitmapbutton") && dw_window_get_data(handle, "_dw_hpixmap_disabled")) - WinInvalidateRect(handle, NULL, FALSE); -} - -/* - * Gets the child window handle with specified ID. - * Parameters: - * handle: Handle to the parent window. - * id: Integer ID of the child. - */ -HWND API dw_window_from_id(HWND handle, int id) -{ - HENUM henum; - HWND child; - char tmpbuf[100]; - - henum = WinBeginEnumWindows(handle); - while((child = WinGetNextWindow(henum)) != NULLHANDLE) - { - int windowid = WinQueryWindowUShort(child, QWS_ID); - HWND found; - - WinQueryClassName(child, 99, tmpbuf); - - /* If the child is a box (frame) then recurse into it */ - if(strncmp(tmpbuf, "#1", 3)==0) - if((found = dw_window_from_id(child, id)) != NULLHANDLE) - return found; - - if(windowid && windowid == id) - { - WinEndEnumWindows(henum); - return child; - } - } - WinEndEnumWindows(henum); - return NULLHANDLE; -} - -/* - * Pack windows (widgets) into a box from the end (or bottom). - * Parameters: - * box: Window handle of the box to be packed into. - * item: Window handle of the item to be back. - * width: Width in pixels of the item or -1 to be self determined. - * height: Height in pixels of the item or -1 to be self determined. - * hsize: TRUE if the window (widget) should expand horizontally to fill space given. - * vsize: TRUE if the window (widget) should expand vertically to fill space given. - * pad: Number of pixels of padding around the item. - */ -void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) -{ - Box *thisbox; - char *funcname = "dw_box_pack_end()"; - - /* - * If you try and pack an item into itself VERY bad things can happen; like at least an - * infinite loop on GTK! Lets be safe! - */ - if(box == item) - { - dw_messagebox(funcname, DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!",box,item); - return; - } - - if(WinWindowFromID(box, FID_CLIENT)) - { - box = WinWindowFromID(box, FID_CLIENT); - thisbox = WinQueryWindowPtr(box, QWP_USER); - hsize = TRUE; - vsize = TRUE; - } - else - thisbox = WinQueryWindowPtr(box, QWP_USER); - if(thisbox) - { - if(thisbox->type == DW_HORZ) - _dw_box_pack_start(box, item, width, height, hsize, vsize, pad, funcname); - else - _dw_box_pack_end(box, item, width, height, hsize, vsize, pad, funcname); - } -} - -void _dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad, char *functionname) -{ - Box *thisbox = WinQueryWindowPtr(box, QWP_USER); - - if(thisbox) - { - int z; - Item *tmpitem, *thisitem = thisbox->items; - char tmpbuf[100]; - HWND frame = (HWND)dw_window_get_data(item, "_dw_combo_box"); - - tmpitem = malloc(sizeof(Item)*(thisbox->count+1)); - - for(z=0;z<thisbox->count;z++) - { - tmpitem[z] = thisitem[z]; - } - - WinQueryClassName(item, 99, tmpbuf); - - if(vsize && !height) - height = 1; - if(hsize && !width) - width = 1; - - if(strncmp(tmpbuf, "#1", 3)==0) - tmpitem[thisbox->count].type = TYPEBOX; - else - { - if ( width == 0 && hsize == FALSE ) - dw_messagebox(functionname, DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item); - if ( height == 0 && vsize == FALSE ) - dw_messagebox(functionname, DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item); - - tmpitem[thisbox->count].type = TYPEITEM; - } - - tmpitem[thisbox->count].hwnd = item; - tmpitem[thisbox->count].origwidth = tmpitem[thisbox->count].width = width; - tmpitem[thisbox->count].origheight = tmpitem[thisbox->count].height = height; - tmpitem[thisbox->count].pad = pad; - if(hsize) - tmpitem[thisbox->count].hsize = SIZEEXPAND; - else - tmpitem[thisbox->count].hsize = SIZESTATIC; - - if(vsize) - tmpitem[thisbox->count].vsize = SIZEEXPAND; - else - tmpitem[thisbox->count].vsize = SIZESTATIC; - - thisbox->items = tmpitem; - - if(thisbox->count) - free(thisitem); - - thisbox->count++; - - /* Don't set the ownership if it's an entryfield or spinbutton */ - WinQueryClassName(item, 99, tmpbuf); - if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 4)!=0 && strncmp(tmpbuf, "#2", 3)!=0) - WinSetOwner(item, box); - WinSetParent(frame ? frame : item, box, FALSE); - } -} - -/* - * Sets the size of a given window (widget). - * Parameters: - * handle: Window (widget) handle. - * width: New width in pixels. - * height: New height in pixels. - */ -void API dw_window_set_usize(HWND handle, ULONG width, ULONG height) -{ - WinSetWindowPos(handle, NULLHANDLE, 0, 0, width, height, SWP_SHOW | SWP_SIZE); -} - -/* - * Returns the width of the screen. - */ -int API dw_screen_width(void) -{ - return WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN); -} - -/* - * Returns the height of the screen. - */ -int API dw_screen_height(void) -{ - return WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN); -} - -/* This should return the current color depth */ -unsigned long API dw_color_depth(void) -{ - HDC hdc = WinOpenWindowDC(HWND_DESKTOP); - long colors; - - DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1, &colors); - DevCloseDC(hdc); - return colors; -} - - -/* - * Sets the position of a given window (widget). - * Parameters: - * handle: Window (widget) handle. - * x: X location from the bottom left. - * y: Y location from the bottom left. - */ -void API dw_window_set_pos(HWND handle, ULONG x, ULONG y) -{ - int myy = _get_frame_height(handle) - (y + _get_height(handle)); - - WinSetWindowPos(handle, NULLHANDLE, x, myy, 0, 0, SWP_MOVE); -} - -/* - * Sets the position and size of a given window (widget). - * Parameters: - * handle: Window (widget) handle. - * x: X location from the bottom left. - * y: Y location from the bottom left. - * width: Width of the widget. - * height: Height of the widget. - */ -void API dw_window_set_pos_size(HWND handle, ULONG x, ULONG y, ULONG width, ULONG height) -{ - int myy = _get_frame_height(handle) - (y + height); - - WinSetWindowPos(handle, NULLHANDLE, x, myy, width, height, SWP_MOVE | SWP_SIZE | SWP_SHOW); -} - -/* - * Gets the position and size of a given window (widget). - * Parameters: - * handle: Window (widget) handle. - * x: X location from the bottom left. - * y: Y location from the bottom left. - * width: Width of the widget. - * height: Height of the widget. - */ -void API dw_window_get_pos_size(HWND handle, ULONG *x, ULONG *y, ULONG *width, ULONG *height) -{ - SWP swp; - WinQueryWindowPos(handle, &swp); - if(x) - *x = swp.x; - if(y) - *y = _get_frame_height(handle) - (swp.y + swp.cy); - if(width) - *width = swp.cx; - if(height) - *height = swp.cy; -} - -/* - * Sets the style of a given window (widget). - * Parameters: - * handle: Window (widget) handle. - * width: New width in pixels. - * height: New height in pixels. - */ -void API dw_window_set_style(HWND handle, ULONG style, ULONG mask) -{ - WinSetWindowBits(handle, QWL_STYLE, style, mask); -} - -/* - * Adds a new page to specified notebook. - * Parameters: - * handle: Window (widget) handle. - * flags: Any additional page creation flags. - * front: If TRUE page is added at the beginning. - */ -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)); -} - -/* - * Remove a page from a notebook. - * Parameters: - * handle: Handle to the notebook widget. - * pageid: ID of the page to be destroyed. - */ -void API dw_notebook_page_destroy(HWND handle, unsigned int pageid) -{ - WinSendMsg(handle, BKM_DELETEPAGE, - MPFROMLONG(pageid), (MPARAM)BKA_SINGLE); -} - -/* - * Queries the currently visible page ID. - * Parameters: - * handle: Handle to the notebook widget. - */ -unsigned long API dw_notebook_page_query(HWND handle) -{ - return (unsigned long)WinSendMsg(handle, BKM_QUERYPAGEID,0L, MPFROM2SHORT(BKA_TOP, BKA_MAJOR)); -} - -/* - * Sets the currently visibale page ID. - * Parameters: - * handle: Handle to the notebook widget. - * pageid: ID of the page to be made visible. - */ -void API dw_notebook_page_set(HWND handle, unsigned int pageid) -{ - WinSendMsg(handle, BKM_TURNTOPAGE, MPFROMLONG(pageid), 0L); -} - -/* - * Sets the text on the specified notebook tab. - * Parameters: - * handle: Notebook handle. - * pageid: Page ID of the tab to set. - * text: Pointer to the text to set. - */ -void API dw_notebook_page_set_text(HWND handle, ULONG pageid, char *text) -{ - WinSendMsg(handle, BKM_SETTABTEXT, - MPFROMLONG(pageid), MPFROMP(text)); -} - -/* - * Sets the text on the specified notebook tab status area. - * Parameters: - * handle: Notebook handle. - * pageid: Page ID of the tab to set. - * text: Pointer to the text to set. - */ -void API dw_notebook_page_set_status_text(HWND handle, ULONG pageid, char *text) -{ - WinSendMsg(handle, BKM_SETSTATUSLINETEXT, - MPFROMLONG(pageid), MPFROMP(text)); -} - -/* - * Packs the specified box into the notebook page. - * Parameters: - * handle: Handle to the notebook to be packed. - * pageid: Page ID in the notebook which is being packed. - * page: Box handle to be packed. - */ -void API dw_notebook_pack(HWND handle, ULONG pageid, HWND page) -{ - HWND tmpbox = dw_box_new(DW_VERT, 0); - - dw_box_pack_start(tmpbox, page, 0, 0, TRUE, TRUE, 0); - WinSubclassWindow(tmpbox, _wndproc); - WinSendMsg(handle, BKM_SETPAGEWINDOWHWND, - MPFROMLONG(pageid), MPFROMHWND(tmpbox)); -} - -/* - * Appends the specified text to the listbox's (or combobox) entry list. - * Parameters: - * handle: Handle to the listbox to be appended to. - * text: Text to append into listbox. - */ -void API dw_listbox_append(HWND handle, char *text) -{ - WinSendMsg(handle, - LM_INSERTITEM, - MPFROMSHORT(LIT_END), - MPFROMP(text)); -} - -/* - * Clears the listbox's (or combobox) list of all entries. - * Parameters: - * handle: Handle to the listbox to be cleared. - */ -void API dw_listbox_clear(HWND handle) -{ - WinSendMsg(handle, - LM_DELETEALL, 0L, 0L); -} - -/* - * Returns the listbox's item count. - * Parameters: - * handle: Handle to the listbox to be cleared. - */ -int API dw_listbox_count(HWND handle) -{ - return (int)WinSendMsg(handle, - LM_QUERYITEMCOUNT,0L, 0L); -} - -/* - * Sets the topmost item in the viewport. - * Parameters: - * handle: Handle to the listbox to be cleared. - * top: Index to the top item. - */ -void API dw_listbox_set_top(HWND handle, int top) -{ - WinSendMsg(handle, - LM_SETTOPINDEX, - MPFROMSHORT(top), - 0L); -} - -/* - * Copies the given index item's text into buffer. - * Parameters: - * handle: Handle to the listbox to be queried. - * index: Index into the list to be queried. - * buffer: Buffer where text will be copied. - * length: Length of the buffer (including NULL). - */ -void API dw_listbox_query_text(HWND handle, unsigned int index, char *buffer, unsigned int length) -{ - WinSendMsg(handle, LM_QUERYITEMTEXT, MPFROM2SHORT(index, length), (MPARAM)buffer); -} - -/* - * Sets the text of a given listbox entry. - * Parameters: - * handle: Handle to the listbox to be queried. - * index: Index into the list to be queried. - * buffer: Buffer where text will be copied. - */ -void API dw_listbox_set_text(HWND handle, unsigned int index, char *buffer) -{ - WinSendMsg(handle, LM_SETITEMTEXT, MPFROMSHORT(index), (MPARAM)buffer); -} - -/* - * Returns the index to the item in the list currently selected. - * Parameters: - * handle: Handle to the listbox to be queried. - */ -unsigned int API dw_listbox_selected(HWND handle) -{ - return (unsigned int)WinSendMsg(handle, - LM_QUERYSELECTION, - MPFROMSHORT(LIT_CURSOR), - 0); -} - -/* - * Returns the index to the current selected item or -1 when done. - * Parameters: - * handle: Handle to the listbox to be queried. - * where: Either the previous return or -1 to restart. - */ -int API dw_listbox_selected_multi(HWND handle, int where) -{ - int place = where; - - if(where == -1) - place = LIT_FIRST; - - place = (int)WinSendMsg(handle, - LM_QUERYSELECTION, - MPFROMSHORT(place),0L); - if(place == LIT_NONE) - return -1; - return place; -} - -/* - * Sets the selection state of a given index. - * Parameters: - * handle: Handle to the listbox to be set. - * index: Item index. - * state: TRUE if selected FALSE if unselected. - */ -void API dw_listbox_select(HWND handle, int index, int state) -{ - char tmpbuf[100]; - - WinSendMsg(handle, LM_SELECTITEM, MPFROMSHORT(index), (MPARAM)state); - - WinQueryClassName(handle, 99, tmpbuf); - - /* If we are setting a combobox call the event handler manually */ - if(strncmp(tmpbuf, "#6", 3)==0) - _run_event(handle, WM_CONTROL, MPFROM2SHORT(0, LN_SELECT), (MPARAM)handle); -} - -/* - * Deletes the item with given index from the list. - * Parameters: - * handle: Handle to the listbox to be set. - * index: Item index. - */ -void API dw_listbox_delete(HWND handle, int index) -{ - WinSendMsg(handle, LM_DELETEITEM, MPFROMSHORT(index), 0); -} - -/* - * Adds text to an MLE box and returns the current point. - * Parameters: - * handle: Handle to the MLE to be queried. - * buffer: Text buffer to be imported. - * startpoint: Point to start entering text. - */ -unsigned int API dw_mle_import(HWND handle, char *buffer, int startpoint) -{ - unsigned long point = startpoint; - PBYTE mlebuf; - - /* Work around 64K limit */ - if(!DosAllocMem((PPVOID) &mlebuf, 65536, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE)) - { - int amount, len = strlen(buffer), written = 0; - - while(written < len) - { - if((len - written) > 65535) - amount = 65535; - else - amount = len - written; - - memcpy(mlebuf, &buffer[written], amount); - mlebuf[amount] = '\0'; - - WinSendMsg(handle, MLM_SETIMPORTEXPORT, MPFROMP(mlebuf), MPFROMLONG(amount+1)); - WinSendMsg(handle, MLM_IMPORT, MPFROMP(&point), MPFROMLONG(amount + 1)); - dw_mle_delete(handle, point, 1); - - written += amount; - } - DosFreeMem(mlebuf); - } - return point - 1; -} - -/* - * Grabs text from an MLE box. - * Parameters: - * handle: Handle to the MLE to be queried. - * buffer: Text buffer to be exported. - * startpoint: Point to start grabbing text. - * length: Amount of text to be grabbed. - */ -void API dw_mle_export(HWND handle, char *buffer, int startpoint, int length) -{ - PBYTE mlebuf; - - /* Work around 64K limit */ - if(!DosAllocMem((PPVOID) &mlebuf, 65535, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE)) - { - int amount, copied, written = 0; - - while(written < length) - { - if((length - written) > 65535) - amount = 65535; - else - amount = length - written; - - WinSendMsg(handle, MLM_SETIMPORTEXPORT, MPFROMP(mlebuf), MPFROMLONG(amount)); - copied = (int)WinSendMsg(handle, MLM_EXPORT, MPFROMP(&startpoint), MPFROMLONG(&amount)); - - if(copied) - { - memcpy(&buffer[written], mlebuf, copied); - - written += copied; - } - else - break; - } - DosFreeMem(mlebuf); - } -} - -/* - * Obtains information about an MLE box. - * Parameters: - * handle: Handle to the MLE to be queried. - * bytes: A pointer to a variable to return the total bytes. - * lines: A pointer to a variable to return the number of lines. - */ -void API dw_mle_query(HWND handle, unsigned long *bytes, unsigned long *lines) -{ - if(bytes) - *bytes = (unsigned long)WinSendMsg(handle, MLM_QUERYTEXTLENGTH, 0, 0); - if(lines) - *lines = (unsigned long)WinSendMsg(handle, MLM_QUERYLINECOUNT, 0, 0); -} - -/* - * Deletes text from an MLE box. - * Parameters: - * handle: Handle to the MLE to be deleted from. - * startpoint: Point to start deleting text. - * length: Amount of text to be deleted. - */ -void API dw_mle_delete(HWND handle, int startpoint, int length) -{ - char *buf = malloc(length+1); - int z, dellen = length; - - dw_mle_export(handle, buf, startpoint, length); - - for(z=0;z<length-1;z++) - { - if(strncmp(&buf[z], "\r\n", 2) == 0) - dellen--; - } - WinSendMsg(handle, MLM_DELETE, MPFROMLONG(startpoint), MPFROMLONG(dellen)); - free(buf); -} - -/* - * Clears all text from an MLE box. - * Parameters: - * handle: Handle to the MLE to be cleared. - */ -void API dw_mle_clear(HWND handle) -{ - unsigned long bytes; - - dw_mle_query(handle, &bytes, NULL); - - WinSendMsg(handle, MLM_DELETE, MPFROMLONG(0), MPFROMLONG(bytes)); -} - -/* - * Sets the visible line of an MLE box. - * Parameters: - * handle: Handle to the MLE to be positioned. - * line: Line to be visible. - */ -void API dw_mle_set_visible(HWND handle, int line) -{ - int tmppnt = (int)WinSendMsg(handle, MLM_CHARFROMLINE, MPFROMLONG(line), 0); - WinSendMsg(handle, MLM_SETSEL, MPFROMLONG(tmppnt), MPFROMLONG(tmppnt)); -} - -/* - * Sets the editablity of an MLE box. - * Parameters: - * handle: Handle to the MLE. - * state: TRUE if it can be edited, FALSE for readonly. - */ -void API dw_mle_set_editable(HWND handle, int state) -{ - WinSendMsg(handle, MLM_SETREADONLY, MPFROMLONG(state ? FALSE : TRUE), 0); -} - -/* - * Sets the word wrap state of an MLE box. - * Parameters: - * handle: Handle to the MLE. - * state: TRUE if it wraps, FALSE if it doesn't. - */ -void API dw_mle_set_word_wrap(HWND handle, int state) -{ - WinSendMsg(handle, MLM_SETWRAP, MPFROMLONG(state), 0); -} - -/* - * Sets the current cursor position of an MLE box. - * Parameters: - * handle: Handle to the MLE to be positioned. - * point: Point to position cursor. - */ -void API dw_mle_set(HWND handle, int point) -{ - WinSendMsg(handle, MLM_SETSEL, MPFROMLONG(point), MPFROMLONG(point)); -} - -/* - * Finds text in an MLE box. - * Parameters: - * handle: Handle to the MLE to be cleared. - * text: Text to search for. - * point: Start point of search. - * flags: Search specific flags. - */ -int API dw_mle_search(HWND handle, char *text, int point, unsigned long flags) -{ - MLE_SEARCHDATA msd; - - /* This code breaks with structure packing set to 1 (/Sp1 in VAC) - * if this is needed we need to add a pragma here. - */ - msd.cb = sizeof(msd); - msd.pchFind = text; - msd.pchReplace = NULL; - msd.cchFind = strlen(text); - msd.cchReplace = 0; - msd.iptStart = point; - msd.iptStop = -1; - - if(WinSendMsg(handle, MLM_SEARCH, MPFROMLONG(MLFSEARCH_SELECTMATCH | flags), (MPARAM)&msd)) - return (int)WinSendMsg(handle, MLM_QUERYSEL,(MPARAM)MLFQS_MAXSEL, 0); - return 0; -} - -/* - * Stops redrawing of an MLE box. - * Parameters: - * handle: Handle to the MLE to freeze. - */ -void API dw_mle_freeze(HWND handle) -{ - WinSendMsg(handle, MLM_DISABLEREFRESH, 0, 0); -} - -/* - * Resumes redrawing of an MLE box. - * Parameters: - * handle: Handle to the MLE to thaw. - */ -void API dw_mle_thaw(HWND handle) -{ - WinSendMsg(handle, MLM_ENABLEREFRESH, 0, 0); -} - -/* - * Returns the range of the percent bar. - * Parameters: - * handle: Handle to the percent bar to be queried. - */ -unsigned int API dw_percent_query_range(HWND handle) -{ - return SHORT2FROMMP(WinSendMsg(handle, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), 0)); -} - -/* - * Sets the percent bar position. - * Parameters: - * handle: Handle to the percent bar to be set. - * position: Position of the percent bar withing the range. - */ -void API dw_percent_set_pos(HWND handle, unsigned int position) -{ - _dw_int_set(handle, position); - WinSendMsg(handle, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), (MPARAM)position); -} - -/* - * Returns the position of the slider. - * Parameters: - * handle: Handle to the slider to be queried. - */ -unsigned int API dw_slider_query_pos(HWND handle) -{ - return (unsigned int)WinSendMsg(handle, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0); -} - -/* - * Sets the slider position. - * Parameters: - * handle: Handle to the slider to be set. - * position: Position of the slider withing the range. - */ -void API dw_slider_set_pos(HWND handle, unsigned int position) -{ - dw_window_set_data(handle, "_dw_slider_value", (void *)position); - WinSendMsg(handle, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), (MPARAM)position); -} - -/* - * Returns the position of the scrollbar. - * Parameters: - * handle: Handle to the scrollbar to be queried. - */ -unsigned int API dw_scrollbar_query_pos(HWND handle) -{ - return (unsigned int)WinSendMsg(handle, SBM_QUERYPOS, 0, 0); -} - -/* - * Sets the scrollbar position. - * Parameters: - * handle: Handle to the scrollbar to be set. - * position: Position of the scrollbar withing the range. - */ -void API dw_scrollbar_set_pos(HWND handle, unsigned int position) -{ - dw_window_set_data(handle, "_dw_scrollbar_value", (void *)position); - WinSendMsg(handle, SBM_SETPOS, (MPARAM)position, 0); -} - -/* - * Sets the scrollbar range. - * Parameters: - * handle: Handle to the scrollbar to be set. - * range: Maximum range value. - * visible: Visible area relative to the range. - */ -void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible) -{ - unsigned int pos = (unsigned int)dw_window_get_data(handle, "_dw_scrollbar_value"); - WinSendMsg(handle, SBM_SETSCROLLBAR, (MPARAM)pos, MPFROM2SHORT(0, (unsigned short)range - visible)); - WinSendMsg(handle, SBM_SETTHUMBSIZE, MPFROM2SHORT((unsigned short)visible, range), 0); - dw_window_set_data(handle, "_dw_scrollbar_visible", (void *)visible); -} - -/* - * Sets the spinbutton value. - * Parameters: - * handle: Handle to the spinbutton to be set. - * position: Current value of the spinbutton. - */ -void API dw_spinbutton_set_pos(HWND handle, long position) -{ - WinSendMsg(handle, SPBM_SETCURRENTVALUE, MPFROMLONG((long)position), 0L); -} - -/* - * Sets the spinbutton limits. - * Parameters: - * handle: Handle to the spinbutton to be set. - * upper: Upper limit. - * lower: Lower limit. - */ -void API dw_spinbutton_set_limits(HWND handle, long upper, long lower) -{ - WinSendMsg(handle, SPBM_SETLIMITS, MPFROMLONG(upper), MPFROMLONG(lower)); -} - -/* - * Sets the entryfield character limit. - * Parameters: - * handle: Handle to the spinbutton to be set. - * limit: Number of characters the entryfield will take. - */ -void API dw_entryfield_set_limit(HWND handle, ULONG limit) -{ - WinSendMsg(handle, EM_SETTEXTLIMIT, (MPARAM)limit, (MPARAM)0); -} - - -/* - * Returns the current value of the spinbutton. - * Parameters: - * handle: Handle to the spinbutton to be queried. - */ -long API dw_spinbutton_query(HWND handle) -{ - long tmpval = 0L; - - WinSendMsg(handle, SPBM_QUERYVALUE, (MPARAM)&tmpval,0L); - return tmpval; -} - -/* - * Returns the state of the checkbox. - * Parameters: - * handle: Handle to the checkbox to be queried. - */ -int API dw_checkbox_query(HWND handle) -{ - return (int)WinSendMsg(handle,BM_QUERYCHECK,0,0); -} - -/* - * Sets the state of the checkbox. - * Parameters: - * handle: Handle to the checkbox to be queried. - * value: TRUE for checked, FALSE for unchecked. - */ -void API dw_checkbox_set(HWND handle, int value) -{ - WinSendMsg(handle,BM_SETCHECK,MPFROMSHORT(value),0); -} - -/* - * Inserts an item into a tree window (widget) after another item. - * Parameters: - * handle: Handle to the tree to be inserted. - * item: Handle to the item to be positioned after. - * title: The text title of the entry. - * icon: Handle to coresponding icon. - * parent: Parent handle or 0 if root. - * itemdata: Item specific data. - */ -HTREEITEM API dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, unsigned long icon, HTREEITEM parent, void *itemdata) -{ - ULONG cbExtra; - PCNRITEM pci; - RECORDINSERT ri; - - if(!item) - item = (HTREEITEM)CMA_FIRST; - - /* Calculate extra bytes needed for each record besides that needed for the - * MINIRECORDCORE structure - */ - - cbExtra = sizeof(CNRITEM) - sizeof(MINIRECORDCORE); - - /* Allocate memory for the parent record */ - - if((pci = (PCNRITEM)_dw_send_msg(handle, CM_ALLOCRECORD, MPFROMLONG(cbExtra), MPFROMSHORT(1), 0)) == 0) - return 0; - - /* Fill in the parent record data */ - - pci->rc.cb = sizeof(MINIRECORDCORE); - pci->rc.pszIcon = strdup(title); - pci->rc.hptrIcon = icon; - - pci->hptrIcon = icon; - pci->user = itemdata; - pci->parent = parent; - - memset(&ri, 0, sizeof(RECORDINSERT)); - - ri.cb = sizeof(RECORDINSERT); - ri.pRecordOrder = (PRECORDCORE)item; - ri.zOrder = (USHORT)CMA_TOP; - ri.cRecordsInsert = 1; - ri.fInvalidateRecord = TRUE; - - /* We are about to insert the child records. Set the parent record to be - * the one we just inserted. - */ - ri.pRecordParent = (PRECORDCORE)parent; - - /* Insert the record */ - WinSendMsg(handle, CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri)); - - return (HTREEITEM)pci; -} - -/* - * Inserts an item into a tree window (widget). - * Parameters: - * handle: Handle to the tree to be inserted. - * title: The text title of the entry. - * icon: Handle to coresponding icon. - * parent: Parent handle or 0 if root. - * itemdata: Item specific data. - */ -HTREEITEM API dw_tree_insert(HWND handle, char *title, unsigned long icon, HTREEITEM parent, void *itemdata) -{ - return dw_tree_insert_after(handle, (HTREEITEM)CMA_END, title, icon, parent, itemdata); -} - -/* - * Sets the text and icon of an item in a tree window (widget). - * Parameters: - * handle: Handle to the tree containing the item. - * item: Handle of the item to be modified. - * title: The text title of the entry. - * icon: Handle to coresponding icon. - */ -void API dw_tree_set(HWND handle, HTREEITEM item, char *title, unsigned long icon) -{ - PCNRITEM pci = (PCNRITEM)item; - - if(!pci) - return; - - if(pci->rc.pszIcon) - free(pci->rc.pszIcon); - - pci->rc.pszIcon = strdup(title); - pci->rc.hptrIcon = icon; - - pci->hptrIcon = icon; - - WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pci, MPFROM2SHORT(1, CMA_TEXTCHANGED)); -} - -/* - * Gets the text an item in a tree window (widget). - * Parameters: - * handle: Handle to the tree containing the item. - * item: Handle of the item to be modified. - */ -char * API dw_tree_get_title(HWND handle, HTREEITEM item) -{ - PCNRITEM pci = (PCNRITEM)item; - - handle = handle; /* keep compiler happy */ - if(pci) - return pci->rc.pszIcon; - return NULL; -} - -/* - * Gets the text an item in a tree window (widget). - * Parameters: - * handle: Handle to the tree containing the item. - * item: Handle of the item to be modified. - */ -HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item) -{ - PCNRITEM pci = (PCNRITEM)item; - - handle = handle; /* keep compiler happy */ - if(pci) - return pci->parent; - return (HTREEITEM)0; -} - -/* - * Sets the item data of a tree item. - * Parameters: - * handle: Handle to the tree containing the item. - * item: Handle of the item to be modified. - * itemdata: User defined data to be associated with item. - */ -void API dw_tree_set_data(HWND handle, HTREEITEM item, void *itemdata) -{ - PCNRITEM pci = (PCNRITEM)item; - - handle = handle; /* keep compiler happy */ - if(!pci) - return; - - pci->user = itemdata; -} - -/* - * Gets the item data of a tree item. - * Parameters: - * handle: Handle to the tree containing the item. - * item: Handle of the item to be modified. - */ -void * API dw_tree_get_data(HWND handle, HTREEITEM item) -{ - PCNRITEM pci = (PCNRITEM)item; - - handle = handle; /* keep compiler happy */ - if(!pci) - return NULL; - return pci->user; -} - -/* - * Sets this item as the active selection. - * Parameters: - * handle: Handle to the tree window (widget) to be selected. - * item: Handle to the item to be selected. - */ -void API dw_tree_item_select(HWND handle, HTREEITEM item) -{ - PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); - - while(pCore) - { - if(pCore->flRecordAttr & CRA_SELECTED) - WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)pCore, MPFROM2SHORT(FALSE, CRA_SELECTED | CRA_CURSORED)); - pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); - } - WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)item, MPFROM2SHORT(TRUE, CRA_SELECTED | CRA_CURSORED)); - lastitem = 0; - lasthcnr = 0; -} - -/* - * Removes all nodes from a tree. - * Parameters: - * handle: Handle to the window (widget) to be cleared. - */ -void API dw_tree_clear(HWND handle) -{ - dw_container_clear(handle, TRUE); -} - -/* - * Expands a node on a tree. - * Parameters: - * handle: Handle to the tree window (widget). - * item: Handle to node to be expanded. - */ -void API dw_tree_expand(HWND handle, HTREEITEM item) -{ - WinSendMsg(handle, CM_EXPANDTREE, MPFROMP(item), 0); -} - -/* - * Collapses a node on a tree. - * Parameters: - * handle: Handle to the tree window (widget). - * item: Handle to node to be collapsed. - */ -void API dw_tree_collapse(HWND handle, HTREEITEM item) -{ - WinSendMsg(handle, CM_COLLAPSETREE, MPFROMP(item), 0); -} - -/* - * Removes a node from a tree. - * Parameters: - * handle: Handle to the window (widget) to be cleared. - * item: Handle to node to be deleted. - */ -void API dw_tree_delete(HWND handle, HTREEITEM item) -{ - PCNRITEM pci = (PCNRITEM)item; - - if(!item) - return; - - if(pci->rc.pszIcon) - { - free(pci->rc.pszIcon); - pci->rc.pszIcon = 0; - } - - WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)&pci, MPFROM2SHORT(1, CMA_INVALIDATE | CMA_FREE)); -} - -/* Some OS/2 specific container structs */ -typedef struct _containerinfo { - int count; - void *data; - HWND handle; -} ContainerInfo; - -/* - * Sets up the container columns. - * Parameters: - * handle: Handle to the container to be configured. - * flags: An array of unsigned longs with column flags. - * titles: An array of strings with column text titles. - * count: The number of columns (this should match the arrays). - * separator: The column number that contains the main separator. - * (this item may only be used in OS/2) - */ -int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator) -{ - PFIELDINFO details, first, left = NULL; - FIELDINFOINSERT detin; - CNRINFO cnri; - int z; - ULONG size = sizeof(RECORDCORE); - ULONG *offStruct = malloc(count * sizeof(ULONG)); - ULONG *tempflags = malloc((count+1) * sizeof(ULONG)); - WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); - ULONG *oldflags = blah ? blah->data : 0; - - if(!offStruct || !tempflags) - return FALSE; - - memcpy(tempflags, flags, count * sizeof(ULONG)); - tempflags[count] = 0; - - blah->data = tempflags; - blah->flags = separator; - - if(oldflags) - free(oldflags); - - while((first = (PFIELDINFO)WinSendMsg(handle, CM_QUERYDETAILFIELDINFO, 0, MPFROMSHORT(CMA_FIRST))) != NULL) - { - WinSendMsg(handle, CM_REMOVEDETAILFIELDINFO, (MPARAM)&first, MPFROM2SHORT(1, CMA_FREE)); - } - - /* Figure out the offsets to the items in the struct */ - for(z=0;z<count;z++) - { - offStruct[z] = size; - if(flags[z] & DW_CFA_BITMAPORICON) - size += sizeof(HPOINTER); - else if(flags[z] & DW_CFA_STRING) - size += sizeof(char *); - else if(flags[z] & DW_CFA_ULONG) - size += sizeof(ULONG); - else if(flags[z] & DW_CFA_DATE) - size += sizeof(CDATE); - else if(flags[z] & DW_CFA_TIME) - size += sizeof(CTIME); - } - - first = details = (PFIELDINFO)WinSendMsg(handle, CM_ALLOCDETAILFIELDINFO, MPFROMLONG(count), 0L); - - if(!first) - { - free(offStruct); - return FALSE; - } - - for(z=0;z<count;z++) - { - if(z==separator-1) - left=details; - details->cb = sizeof(FIELDINFO); - details->flData = flags[z]; - details->flTitle = CFA_FITITLEREADONLY; - details->pTitleData = titles[z]; - details->offStruct = offStruct[z]; - details = details->pNextFieldInfo; - } - - detin.cb = sizeof(FIELDINFOINSERT); - detin.fInvalidateFieldInfo = FALSE; - detin.pFieldInfoOrder = (PFIELDINFO) CMA_FIRST; - detin.cFieldInfoInsert = (ULONG)count; - - WinSendMsg(handle, CM_INSERTDETAILFIELDINFO, MPFROMP(first), MPFROMP(&detin)); - - if(count > separator && separator > 0) - { - cnri.cb = sizeof(CNRINFO); - cnri.pFieldInfoLast = left; - cnri.xVertSplitbar = 150; - - WinSendMsg(handle, CM_SETCNRINFO, MPFROMP(&cnri), MPFROMLONG(CMA_PFIELDINFOLAST | CMA_XVERTSPLITBAR)); - } - - cnri.flWindowAttr = CV_DETAIL | CV_MINI | CA_DETAILSVIEWTITLES; - cnri.slBitmapOrIcon.cx = 16; - cnri.slBitmapOrIcon.cy = 16; - - WinSendMsg(handle, CM_SETCNRINFO, &cnri, MPFROMLONG(CMA_FLWINDOWATTR | CMA_SLBITMAPORICON)); - - free(offStruct); - return TRUE; -} - -/* - * Sets up the filesystem columns, note: filesystem always has an icon/filename field. - * Parameters: - * handle: Handle to the container to be configured. - * flags: An array of unsigned longs with column flags. - * titles: An array of strings with column text titles. - * count: The number of columns (this should match the arrays). - */ -int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count) -{ - char **newtitles = malloc(sizeof(char *) * (count + 2)); - unsigned long *newflags = malloc(sizeof(unsigned long) * (count + 2)); - - newtitles[0] = "Icon"; - newtitles[1] = "Filename"; - - newflags[0] = DW_CFA_BITMAPORICON | DW_CFA_CENTER | DW_CFA_HORZSEPARATOR | DW_CFA_SEPARATOR; - newflags[1] = DW_CFA_STRING | DW_CFA_LEFT | DW_CFA_HORZSEPARATOR; - - memcpy(&newtitles[2], titles, sizeof(char *) * count); - memcpy(&newflags[2], flags, sizeof(unsigned long) * count); - - dw_container_setup(handle, newflags, newtitles, count + 2, count ? 2 : 0); - - free(newtitles); - free(newflags); - return TRUE; -} - -/* - * Obtains an icon from a module (or header in GTK). - * Parameters: - * module: Handle to module (DLL) in OS/2 and Windows. - * id: A unsigned long id int the resources on OS/2 and - * Windows, on GTK this is converted to a pointer - * to an embedded XPM. - */ -unsigned long API dw_icon_load(unsigned long module, unsigned long id) -{ - return WinLoadPointer(HWND_DESKTOP,module,id); -} - -/* - * Obtains an icon from a file. - * Parameters: - * filename: Name of the file, omit extention to have - * DW pick the appropriate file extension. - * (ICO on OS/2 or Windows, XPM on Unix) - */ -unsigned long API dw_icon_load_from_file(char *filename) -{ - char *file = alloca(strlen(filename) + 5); - - if(!file) - return 0; - - strcpy(file, filename); - - /* check if we can read from this file (it exists and read permission) */ - if(access(file, 04) != 0) - { - /* Try with .bmp extention */ - strcat(file, ".ico"); - if(access(file, 04) != 0) - return 0; - } - return WinLoadFileIcon(file, FALSE); -} - -/* - * Frees a loaded resource in OS/2 and Windows. - * Parameters: - * handle: Handle to icon returned by dw_icon_load(). - */ -void API dw_icon_free(unsigned long handle) -{ - WinDestroyPointer(handle); -} - -/* - * Allocates memory used to populate a container. - * Parameters: - * handle: Handle to the container window (widget). - * rowcount: The number of items to be populated. - */ -void * API dw_container_alloc(HWND handle, int rowcount) -{ - WindowData *wd = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); - ULONG *flags = wd ? wd->data : 0; - int z, size = 0, totalsize, count = 0; - PRECORDCORE temp; - ContainerInfo *ci; - void *blah = NULL; - - if(!flags || rowcount < 1) - return NULL; - - while(flags[count]) - count++; - - /* Figure out the offsets to the items in the struct */ - for(z=0;z<count;z++) - { - if(flags[z] & DW_CFA_BITMAPORICON) - size += sizeof(HPOINTER); - else if(flags[z] & DW_CFA_STRING) - size += sizeof(char *); - else if(flags[z] & DW_CFA_ULONG) - size += sizeof(ULONG); - else if(flags[z] & DW_CFA_DATE) - size += sizeof(CDATE); - else if(flags[z] & DW_CFA_TIME) - size += sizeof(CTIME); - } - - totalsize = size + sizeof(RECORDCORE); - - z = 0; - - if(!(blah = (void *)_dw_send_msg(handle, CM_ALLOCRECORD, MPFROMLONG(size), MPFROMLONG(rowcount), 0))) - return NULL; - - temp = (PRECORDCORE)blah; - - for(z=0;z<rowcount;z++) - { - temp->cb = totalsize; - temp = temp->preccNextRecord; - } - - ci = malloc(sizeof(struct _containerinfo)); - - ci->count = rowcount; - ci->data = blah; - ci->handle = handle; - - return (void *)ci; -} - -/* Internal function that does the work for set_item and change_item */ -void _dw_container_set_item(HWND handle, PRECORDCORE temp, int column, int row, void *data) -{ - WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); - ULONG totalsize, size = 0, *flags = blah ? blah->data : 0; - int z, currentcount; - CNRINFO cnr; - void *dest; - - if(!flags) - return; - - if(!_dw_send_msg(handle, CM_QUERYCNRINFO, (MPARAM)&cnr, MPFROMSHORT(sizeof(CNRINFO)), 0)) - return; - - currentcount = cnr.cRecords; - - /* Figure out the offsets to the items in the struct */ - for(z=0;z<column;z++) - { - if(flags[z] & DW_CFA_BITMAPORICON) - size += sizeof(HPOINTER); - else if(flags[z] & DW_CFA_STRING) - size += sizeof(char *); - else if(flags[z] & DW_CFA_ULONG) - size += sizeof(ULONG); - else if(flags[z] & DW_CFA_DATE) - size += sizeof(CDATE); - else if(flags[z] & DW_CFA_TIME) - size += sizeof(CTIME); - } - - totalsize = size + sizeof(RECORDCORE); - - for(z=0;z<(row-currentcount);z++) - temp = temp->preccNextRecord; - - dest = (void *)(((ULONG)temp)+((ULONG)totalsize)); - - if(flags[column] & DW_CFA_BITMAPORICON) - memcpy(dest, data, sizeof(HPOINTER)); - else if(flags[column] & DW_CFA_STRING) - { - char **newstr = (char **)data, **str = dest; - - if(*str) - free(*str); - - if(newstr && *newstr) - *str = strdup(*newstr); - else - *str = NULL; - } - else if(flags[column] & DW_CFA_ULONG) - memcpy(dest, data, sizeof(ULONG)); - else if(flags[column] & DW_CFA_DATE) - memcpy(dest, data, sizeof(CDATE)); - else if(flags[column] & DW_CFA_TIME) - memcpy(dest, data, sizeof(CTIME)); -} - -/* Internal function that free()s any strings allocated for a container item */ -void _dw_container_free_strings(HWND handle, PRECORDCORE temp) -{ - WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); - ULONG totalsize, size = 0, *flags = blah ? blah->data : 0; - int z, count = 0; - - if(!flags) - return; - - while(flags[count]) - count++; - - /* Figure out the offsets to the items in the struct */ - for(z=0;z<count;z++) - { - if(flags[z] & DW_CFA_BITMAPORICON) - size += sizeof(HPOINTER); - else if(flags[z] & DW_CFA_STRING) - { - char **str; - - totalsize = size + sizeof(RECORDCORE); - - str = (char **)(((ULONG)temp)+((ULONG)totalsize)); - - if(*str) - { - free(*str); - *str = NULL; - } - size += sizeof(char *); - } - else if(flags[z] & DW_CFA_ULONG) - size += sizeof(ULONG); - else if(flags[z] & DW_CFA_DATE) - size += sizeof(CDATE); - else if(flags[z] & DW_CFA_TIME) - size += sizeof(CTIME); - } -} - -/* - * Sets an item in specified row and column to the given data. - * Parameters: - * handle: Handle to the container window (widget). - * pointer: Pointer to the allocated memory in dw_container_alloc(). - * column: Zero based column of data being set. - * row: Zero based row of data being set. - * data: Pointer to the data to be added. - */ -void API dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data) -{ - ContainerInfo *ci = (ContainerInfo *)pointer; - - if(!ci) - return; - - _dw_container_set_item(handle, (PRECORDCORE)ci->data, column, row, data); -} - -/* - * Changes an existing item in specified row and column to the given data. - * Parameters: - * handle: Handle to the container window (widget). - * column: Zero based column of data being set. - * row: Zero based row of data being set. - * data: Pointer to the data to be added. - */ -void API dw_container_change_item(HWND handle, int column, 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) - { - _dw_container_set_item(handle, pCore, column, 0, data); - WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_NOREPOSITION | CMA_TEXTCHANGED)); - return; - } - pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); - count++; - } -} - -/* - * Sets an item in specified row and column to the given data. - * Parameters: - * handle: Handle to the container window (widget). - * pointer: Pointer to the allocated memory in dw_container_alloc(). - * column: Zero based column of data being set. - * row: Zero based row of data being set. - * data: Pointer to the data to be added. - */ -void API dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, unsigned long icon) -{ - dw_container_set_item(handle, pointer, 0, row, (void *)&icon); - dw_container_set_item(handle, pointer, 1, row, (void *)&filename); -} - -/* - * Sets an item in specified row and column to the given data. - * Parameters: - * handle: Handle to the container window (widget). - * pointer: Pointer to the allocated memory in dw_container_alloc(). - * column: Zero based column of data being set. - * row: Zero based row of data being set. - * data: Pointer to the data to be added. - */ -void API dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data) -{ - dw_container_set_item(handle, pointer, column + 2, row, data); -} - -/* - * Sets the width of a column in the container. - * Parameters: - * handle: Handle to window (widget) of container. - * column: Zero based column of width being set. - * width: Width of column in pixels. - */ -void API dw_container_set_column_width(HWND handle, int column, int width) -{ - handle = handle; /* keep compiler happy */ - column = column; /* keep compiler happy */ - width = width; /* keep compiler happy */ -} - -/* - * Sets the title 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. - * title: String title of the item. - */ -void API dw_container_set_row_title(void *pointer, int row, char *title) -{ - 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->pszIcon = title; - temp->pszName = title; - temp->pszText = title; -} - -/* - * Sets the title of a row in the container. - * Parameters: - * handle: Handle to the container window (widget). - * pointer: Pointer to the allocated memory in dw_container_alloc(). - * rowcount: The number of rows to be inserted. - */ -void API dw_container_insert(HWND handle, void *pointer, int rowcount) -{ - RECORDINSERT recin; - ContainerInfo *ci = (ContainerInfo *)pointer; - - if(!ci) - return; - - recin.cb = sizeof(RECORDINSERT); - recin.pRecordOrder = (PRECORDCORE)CMA_END; - recin.pRecordParent = NULL; - recin.zOrder = CMA_TOP; - recin.fInvalidateRecord = TRUE; - recin.cRecordsInsert = rowcount; - - _dw_send_msg(handle, CM_INSERTRECORD, MPFROMP(ci->data), MPFROMP(&recin), 0); - - free(ci); -} - -/* - * Removes all rows from a container. - * Parameters: - * handle: Handle to the window (widget) to be cleared. - * redraw: TRUE to cause the container to redraw immediately. - */ -void API dw_container_clear(HWND handle, int redraw) -{ - PCNRITEM pCore; - int container = (int)dw_window_get_data(handle, "_dw_container"); - - if(hwndEmph == handle) - _clear_emphasis(); - - pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); - - while(pCore) - { - if(container) - _dw_container_free_strings(handle, (PRECORDCORE)pCore); - else - { - /* Free icon text */ - if(pCore->rc.pszIcon) - { - free(pCore->rc.pszIcon); - pCore->rc.pszIcon = 0; - } - } - pCore = (PCNRITEM)pCore->rc.preccNextRecord;/*WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));*/ - } - _dw_send_msg(handle, CM_REMOVERECORD, (MPARAM)0L, MPFROM2SHORT(0, (redraw ? CMA_INVALIDATE : 0) | CMA_FREE), -1); -} - -/* - * Removes the first x rows from a container. - * Parameters: - * handle: Handle to the window (widget) to be deleted from. - * rowcount: The number of rows to be deleted. - */ -void API dw_container_delete(HWND handle, int rowcount) -{ - RECORDCORE *last, **prc = malloc(sizeof(RECORDCORE *) * rowcount); - int current = 1; - - prc[0] = last = (RECORDCORE *)WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); - - while(last && current < rowcount) - { - _dw_container_free_strings(handle, last); - prc[current] = last = (RECORDCORE *)WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)last, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); - current++; - } - - _dw_send_msg(handle, CM_REMOVERECORD, (MPARAM)prc, MPFROM2SHORT(current, CMA_INVALIDATE | CMA_FREE), -1); - - free(prc); -} - -/* - * Scrolls container up or down. - * Parameters: - * handle: Handle to the window (widget) to be scrolled. - * direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or - * DW_SCROLL_BOTTOM. (rows is ignored for last two) - * rows: The number of rows to be scrolled. - */ -void API dw_container_scroll(HWND handle, int direction, long rows) -{ - rows = rows; /* keep compiler happy */ - switch(direction) - { - case DW_SCROLL_TOP: - WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(-10000000)); - break; - case DW_SCROLL_BOTTOM: - WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(10000000)); - break; - } -} - -/* - * Starts a new query of a container. - * Parameters: - * handle: Handle to the window (widget) to be queried. - * flags: If this parameter is DW_CRA_SELECTED it will only - * return items that are currently selected. Otherwise - * it will return all records in the container. - */ -char * API dw_container_query_start(HWND handle, unsigned long flags) -{ - pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); - if(pCore) - { - if(flags) - { - while(pCore) - { - if(pCore->flRecordAttr & flags) - return pCore->pszIcon; - pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); - } - } - else - return pCore->pszIcon; - } - return NULL; -} - -/* - * Continues an existing query of a container. - * Parameters: - * handle: Handle to the window (widget) to be queried. - * flags: If this parameter is DW_CRA_SELECTED it will only - * return items that are currently selected. Otherwise - * it will return all records in the container. - */ -char * API dw_container_query_next(HWND handle, unsigned long flags) -{ - pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); - if(pCore) - { - if(flags) - { - while(pCore) - { - if(pCore->flRecordAttr & flags) - return pCore->pszIcon; - - pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); - } - } - else - return pCore->pszIcon; - } - return NULL; -} - -/* - * 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(HWND handle, char *text) -{ - RECTL viewport, item; - - pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); - while(pCore) - { - if((char *)pCore->pszIcon == text) - { - 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 text speficied. - * Parameters: - * handle: Handle to the window (widget). - * text: Text usually returned by dw_container_query(). - */ -void API dw_container_delete_row(HWND handle, char *text) -{ - PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); - - while(pCore) - { - if((char *)pCore->pszIcon == text) - { - 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)); - } -} - -/* - * Optimizes the column widths so that all data is visible. - * Parameters: - * handle: Handle to the window (widget) to be optimized. - */ -void API dw_container_optimize(HWND handle) -{ - WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); - RECTL item; - PRECORDCORE pCore = NULL; - int max = 0; - - if(blah && !blah->flags) - return; - - pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); - while(pCore) - { - QUERYRECORDRECT qrr; - int vector; - - qrr.cb = sizeof(QUERYRECORDRECT); - qrr.pRecord = pCore; - qrr.fRightSplitWindow = 0; - qrr.fsExtent = CMA_TEXT; - - WinSendMsg(handle, CM_QUERYRECORDRECT, (MPARAM)&item, (MPARAM)&qrr); - - vector = item.xRight - item.xLeft; - - if(vector > max) - max = vector; - - pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); - } - - if(max) - { - CNRINFO cnri; - - cnri.cb = sizeof(CNRINFO); - cnri.xVertSplitbar = max; - - WinSendMsg(handle, CM_SETCNRINFO, MPFROMP(&cnri), MPFROMLONG(CMA_XVERTSPLITBAR)); - } -} - -/* - * Inserts an icon into the taskbar. - * Parameters: - * handle: Window handle that will handle taskbar icon messages. - * icon: Icon handle to display in the taskbar. - * bubbletext: Text to show when the mouse is above the icon. - */ -void dw_taskbar_insert(HWND handle, unsigned long icon, char *bubbletext) -{ - handle = handle; - icon = icon; - bubbletext = bubbletext; - /* TODO */ -} - -/* - * Deletes an icon from the taskbar. - * Parameters: - * handle: Window handle that was used with dw_taskbar_insert(). - * icon: Icon handle that was used with dw_taskbar_insert(). - */ -void dw_taskbar_delete(HWND handle, unsigned long icon) -{ - handle = handle; - icon = icon; - /* TODO */ -} - -/* - * Creates a rendering context widget (window) to be packed. - * Parameters: - * id: An id to be used with dw_window_from_id. - * Returns: - * A handle to the widget or NULL on failure. - */ -HWND API dw_render_new(unsigned long id) -{ - HWND hwndframe = WinCreateWindow(HWND_OBJECT, - WC_FRAME, - NULL, - WS_VISIBLE | - FS_NOBYTEALIGN, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - WinSubclassWindow(hwndframe, _RendProc); - return hwndframe; -} - -/* Sets the current foreground drawing color. - * Parameters: - * red: red value. - * green: green value. - * blue: blue value. - */ -void API dw_color_foreground_set(unsigned long value) -{ - _foreground = value; -} - -/* Sets the current background drawing color. - * Parameters: - * red: red value. - * green: green value. - * blue: blue value. - */ -void API dw_color_background_set(unsigned long value) -{ - _background = value; -} - -HPS _set_hps(HPS hps) -{ - LONG alTable[2]; - - alTable[0] = DW_RED_VALUE(_foreground) << 16 | DW_GREEN_VALUE(_foreground) << 8 | DW_BLUE_VALUE(_foreground); - alTable[1] = DW_RED_VALUE(_background) << 16 | DW_GREEN_VALUE(_background) << 8 | DW_BLUE_VALUE(_background); - - GpiCreateLogColorTable(hps, - LCOL_RESET, - LCOLF_CONSECRGB, - 16, - 2, - alTable); - if(_foreground & DW_RGB_COLOR) - GpiSetColor(hps, 16); - else - GpiSetColor(hps, _internal_color(_foreground)); - if(_background & DW_RGB_COLOR) - GpiSetBackColor(hps, 17); - else - GpiSetBackColor(hps, _internal_color(_background)); - return hps; -} - -HPS _set_colors(HWND handle) -{ - HPS hps = WinGetPS(handle); - - _set_hps(hps); - return hps; -} - -/* Draw a point on a window (preferably a render window). - * Parameters: - * handle: Handle to the window. - * pixmap: Handle to the pixmap. (choose only one of these) - * x: X coordinate. - * y: Y coordinate. - */ -void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y) -{ - HPS hps; - int height; - POINTL ptl; - - if(handle) - { - hps = _set_colors(handle); - height = _get_height(handle); - } - else if(pixmap) - { - hps = _set_hps(pixmap->hps); - height = pixmap->height; - } - else - return; - - ptl.x = x; - ptl.y = height - y - 1; - - GpiSetPel(hps, &ptl); - if(!pixmap) - WinReleasePS(hps); -} - -/* Draw a line on a window (preferably a render window). - * Parameters: - * handle: Handle to the window. - * pixmap: Handle to the pixmap. (choose only one of these) - * x1: First X coordinate. - * y1: First Y coordinate. - * x2: Second X coordinate. - * y2: Second Y coordinate. - */ -void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2) -{ - HPS hps; - int height; - POINTL ptl[2]; - - if(handle) - { - hps = _set_colors(handle); - height = _get_height(handle); - } - else if(pixmap) - { - hps = _set_hps(pixmap->hps); - height = pixmap->height; - } - else - return; - - ptl[0].x = x1; - ptl[0].y = height - y1 - 1; - ptl[1].x = x2; - ptl[1].y = height - y2 - 1; - - GpiMove(hps, &ptl[0]); - GpiLine(hps, &ptl[1]); - - if(!pixmap) - WinReleasePS(hps); -} - - -void _CopyFontSettings(HPS hpsSrc, HPS hpsDst) -{ - FONTMETRICS fm; - FATTRS fat; - SIZEF sizf; - - GpiQueryFontMetrics(hpsSrc, sizeof(FONTMETRICS), &fm); - - memset(&fat, 0, sizeof(fat)); - - fat.usRecordLength = sizeof(FATTRS); - fat.lMatch = fm.lMatch; - strcpy(fat.szFacename, fm.szFacename); - - GpiCreateLogFont(hpsDst, 0, 1L, &fat); - GpiSetCharSet(hpsDst, 1L); - - sizf.cx = MAKEFIXED(fm.lEmInc,0); - sizf.cy = MAKEFIXED(fm.lMaxBaselineExt,0); - GpiSetCharBox(hpsDst, &sizf ); -} - -/* Draw text on a window (preferably a render window). - * Parameters: - * handle: Handle to the window. - * pixmap: Handle to the pixmap. (choose only one of these) - * x: X coordinate. - * y: Y coordinate. - * text: Text to be displayed. - */ -void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text) -{ - HPS hps; - int z, height; - RECTL rcl; - char fontname[128]; - POINTL aptl[TXTBOX_COUNT]; - - if(handle) - { - hps = _set_colors(handle); - height = _get_height(handle); - _GetPPFont(handle, fontname); - } - else if(pixmap) - { - HPS pixmaphps = WinGetPS(pixmap->handle); - - hps = _set_hps(pixmap->hps); - height = pixmap->height; - _GetPPFont(pixmap->handle, fontname); - _CopyFontSettings(pixmaphps, hps); - WinReleasePS(pixmaphps); - } - else - return; - - for(z=0;z<strlen(fontname);z++) - { - if(fontname[z]=='.') - break; - } - - GpiQueryTextBox(hps, strlen(text), text, TXTBOX_COUNT, aptl); - - rcl.xLeft = x; - rcl.yTop = height - y; - rcl.yBottom = rcl.yTop - (aptl[TXTBOX_TOPLEFT].y - aptl[TXTBOX_BOTTOMLEFT].y); - rcl.xRight = rcl.xLeft + (aptl[TXTBOX_TOPRIGHT].x - aptl[TXTBOX_TOPLEFT].x); - - if(_background == DW_CLR_DEFAULT) - WinDrawText(hps, -1, text, &rcl, DT_TEXTATTRS, DT_TEXTATTRS, DT_VCENTER | DT_LEFT | DT_TEXTATTRS); - else - WinDrawText(hps, -1, text, &rcl, _internal_color(_foreground), _internal_color(_background), DT_VCENTER | DT_LEFT | DT_ERASERECT); - - if(!pixmap) - WinReleasePS(hps); -} - -/* Query the width and height of a text string. - * Parameters: - * handle: Handle to the window. - * pixmap: Handle to the pixmap. (choose only one of these) - * text: Text to be queried. - * width: Pointer to a variable to be filled in with the width. - * height Pointer to a variable to be filled in with the height. - */ -void API dw_font_text_extents(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height) -{ - HPS hps; - POINTL aptl[TXTBOX_COUNT]; - - if(handle) - { - hps = _set_colors(handle); - } - else if(pixmap) - { - HPS pixmaphps = WinGetPS(pixmap->handle); - - hps = _set_hps(pixmap->hps); - _CopyFontSettings(pixmaphps, hps); - WinReleasePS(pixmaphps); - } - else - return; - - GpiQueryTextBox(hps, strlen(text), text, TXTBOX_COUNT, aptl); - - if(width) - *width = aptl[TXTBOX_TOPRIGHT].x - aptl[TXTBOX_TOPLEFT].x; - - if(height) - *height = aptl[TXTBOX_TOPLEFT].y - aptl[TXTBOX_BOTTOMLEFT].y; - - if(!pixmap) - WinReleasePS(hps); -} - -/* Draw a rectangle on a window (preferably a render window). - * Parameters: - * handle: Handle to the window. - * pixmap: Handle to the pixmap. (choose only one of these) - * fill: Fill box TRUE or FALSE. - * x: X coordinate. - * y: Y coordinate. - * width: Width of rectangle. - * height: Height of rectangle. - */ -void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height) -{ - HPS hps; - int thisheight; - POINTL ptl[2]; - - if(handle) - { - hps = _set_colors(handle); - thisheight = _get_height(handle); - } - else if(pixmap) - { - hps = _set_hps(pixmap->hps); - thisheight = pixmap->height; - } - else - return; - - ptl[0].x = x; - ptl[0].y = thisheight - y - 1; - ptl[1].x = x + width - 1; - ptl[1].y = thisheight - y - height; - - GpiMove(hps, &ptl[0]); - GpiBox(hps, fill ? DRO_OUTLINEFILL : DRO_OUTLINE, &ptl[1], 0, 0); - - if(!pixmap) - WinReleasePS(hps); -} - -/* Call this after drawing to the screen to make sure - * anything you have drawn is visible. - */ -void API dw_flush(void) -{ -} - -/* - * Creates a pixmap with given parameters. - * Parameters: - * handle: Window handle the pixmap is associated with. - * width: Width of the pixmap in pixels. - * height: Height of the pixmap in pixels. - * depth: Color depth of the pixmap. - * Returns: - * A handle to a pixmap or NULL on failure. - */ -HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth) -{ - BITMAPINFOHEADER bmih; - SIZEL sizl = { 0, 0 }; - HPIXMAP pixmap; - HDC hdc; - HPS hps; - ULONG ulFlags; - LONG cPlanes, cBitCount; - - if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) - return NULL; - - hps = WinGetPS(handle); - - hdc = GpiQueryDevice(hps); - ulFlags = GpiQueryPS(hps, &sizl); - - pixmap->handle = handle; - pixmap->hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc); - pixmap->hps = GpiCreatePS (dwhab, pixmap->hdc, &sizl, ulFlags | GPIA_ASSOC); - - DevQueryCaps(hdc, CAPS_COLOR_PLANES , 1L, &cPlanes); - if (!depth) - { - DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1L, &cBitCount); - depth = cBitCount; - } - - memset(&bmih, 0, sizeof(BITMAPINFOHEADER)); - bmih.cbFix = sizeof(BITMAPINFOHEADER); - bmih.cx = (SHORT)width; - bmih.cy = (SHORT)height; - bmih.cPlanes = (SHORT)cPlanes; - bmih.cBitCount = (SHORT)depth; - - pixmap->width = width; pixmap->height = height; - - pixmap->hbm = GpiCreateBitmap(pixmap->hps, (PBITMAPINFOHEADER2)&bmih, 0L, NULL, NULL); - - GpiSetBitmap(pixmap->hps, pixmap->hbm); - - if (depth>8) - GpiCreateLogColorTable(pixmap->hps, LCOL_PURECOLOR, LCOLF_RGB, 0, 0, NULL ); - - WinReleasePS(hps); - - return pixmap; -} - -/* - * Creates a pixmap from a file. - * Parameters: - * handle: Window handle the pixmap is associated with. - * filename: Name of the file, omit extention to have - * DW pick the appropriate file extension. - * (BMP on OS/2 or Windows, XPM on Unix) - * Returns: - * A handle to a pixmap or NULL on failure. - */ -HPIXMAP API dw_pixmap_new_from_file(HWND handle, char *filename) -{ - HPIXMAP pixmap; - char *file = alloca(strlen(filename) + 5); - - if(!file || !(pixmap = calloc(1,sizeof(struct _hpixmap)))) - return NULL; - - strcpy(file, filename); - - /* check if we can read from this file (it exists and read permission) */ - if(access(file, 04) != 0) - { - /* Try with .bmp extention */ - strcat(file, ".bmp"); - if(access(file, 04) != 0) - { - free(pixmap); - return NULL; - } - } - - /* Try to load the bitmap from file */ - if(!_load_bitmap_file(file, handle, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height)) - { - free(pixmap); - return NULL; - } - - /* Success fill in other values */ - pixmap->handle = handle; - - return pixmap; -} - -/* - * Creates a pixmap from internal resource graphic specified by id. - * Parameters: - * handle: Window handle the pixmap is associated with. - * id: Resource ID associated with requested pixmap. - * Returns: - * A handle to a pixmap or NULL on failure. - */ -HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id) -{ - BITMAPINFOHEADER bmih; - SIZEL sizl = { 0, 0 }; - HPIXMAP pixmap; - HDC hdc; - HPS hps; - ULONG ulFlags; - - if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) - return NULL; - - hps = WinGetPS(handle); - - hdc = GpiQueryDevice(hps); - ulFlags = GpiQueryPS(hps, &sizl); - - pixmap->hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc); - pixmap->hps = GpiCreatePS (dwhab, pixmap->hdc, &sizl, ulFlags | GPIA_ASSOC); - - pixmap->hbm = GpiLoadBitmap(pixmap->hps, NULLHANDLE, id, 0, 0); - - GpiQueryBitmapParameters(pixmap->hbm, &bmih); - - GpiSetBitmap(pixmap->hps, pixmap->hbm); - - pixmap->width = bmih.cx; pixmap->height = bmih.cy; - - WinReleasePS(hps); - - return pixmap; -} - -/* - * Destroys an allocated pixmap. - * Parameters: - * pixmap: Handle to a pixmap returned by - * dw_pixmap_new.. - */ -void API dw_pixmap_destroy(HPIXMAP pixmap) -{ - GpiSetBitmap(pixmap->hps, NULLHANDLE); - GpiDeleteBitmap(pixmap->hbm); - GpiAssociate(pixmap->hps, NULLHANDLE); - GpiDestroyPS(pixmap->hps); - DevCloseDC(pixmap->hdc); - free(pixmap); -} - -/* - * Copies from one item to another. - * Parameters: - * dest: Destination window handle. - * destp: Destination pixmap. (choose only one). - * xdest: X coordinate of destination. - * ydest: Y coordinate of destination. - * width: Width of area to copy. - * height: Height of area to copy. - * src: Source window handle. - * srcp: Source pixmap. (choose only one). - * xsrc: X coordinate of source. - * ysrc: Y coordinate of source. - */ -void API dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc) -{ - HPS hpsdest; - HPS hpssrc; - POINTL ptl[4]; - int destheight, srcheight; - - if(dest) - { - hpsdest = WinGetPS(dest); - destheight = _get_height(dest); - } - else if(destp) - { - hpsdest = destp->hps; - destheight = destp->height; - } - else - return; - - if(src) - { - hpssrc = WinGetPS(src); - srcheight = _get_height(src); - } - else if(srcp) - { - hpssrc = srcp->hps; - srcheight = srcp->height; - } - else - { - if(!destp) - WinReleasePS(hpsdest); - return; - } - - ptl[0].x = xdest; - ptl[0].y = (destheight - ydest) - height; - ptl[1].x = ptl[0].x + width; - ptl[1].y = destheight - ydest; - ptl[2].x = xsrc; - ptl[2].y = srcheight - (ysrc + height); - ptl[3].x = ptl[2].x + width; - ptl[3].y = ptl[2].y + height; - - GpiBitBlt(hpsdest, hpssrc, 4, ptl, ROP_SRCCOPY, BBO_IGNORE); - - if(!destp) - WinReleasePS(hpsdest); - if(!srcp) - WinReleasePS(hpssrc); -} - -/* - * Emits a beep. - * Parameters: - * freq: Frequency. - * dur: Duration. - */ -void API dw_beep(int freq, int dur) -{ - DosBeep(freq, dur); -} - -/* Open a shared library and return a handle. - * Parameters: - * name: Base name of the shared library. - * handle: Pointer to a module handle, - * will be filled in with the handle. - */ -int API dw_module_load(char *name, HMOD *handle) -{ - char objnamebuf[300] = ""; - - return DosLoadModule(objnamebuf, sizeof(objnamebuf), name, handle); -} - -/* Queries the address of a symbol within open handle. - * Parameters: - * handle: Module handle returned by dw_module_load() - * name: Name of the symbol you want the address of. - * func: A pointer to a function pointer, to obtain - * the address. - */ -int API dw_module_symbol(HMOD handle, char *name, void**func) -{ - return DosQueryProcAddr(handle, 0, name, (PFN*)func); -} - -/* Frees the shared library previously opened. - * Parameters: - * handle: Module handle returned by dw_module_load() - */ -int API dw_module_close(HMOD handle) -{ - DosFreeModule(handle); - return 0; -} - -/* - * Returns the handle to an unnamed mutex semaphore. - */ -HMTX API dw_mutex_new(void) -{ - HMTX mutex; - - DosCreateMutexSem(NULL, &mutex, 0, FALSE); - return mutex; -} - -/* - * Closes a semaphore created by dw_mutex_new(). - * Parameters: - * mutex: The handle to the mutex returned by dw_mutex_new(). - */ -void API dw_mutex_close(HMTX mutex) -{ - DosCloseMutexSem(mutex); -} - -/* - * Tries to gain access to the semaphore, if it can't it blocks. - * If we are in a callback we must keep the message loop running - * while blocking. - * Parameters: - * mutex: The handle to the mutex returned by dw_mutex_new(). - */ -void API dw_mutex_lock(HMTX mutex) -{ - if(_dwtid == dw_thread_id()) - { - int rc = DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN); - - while(rc == ERROR_TIMEOUT) - { - dw_main_sleep(10); - rc = DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN); - } - } - else - DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT); -} - -/* - * Reliquishes the access to the semaphore. - * Parameters: - * mutex: The handle to the mutex returned by dw_mutex_new(). - */ -void API dw_mutex_unlock(HMTX mutex) -{ - DosReleaseMutexSem(mutex); -} - -/* - * Returns the handle to an unnamed event semaphore. - */ -HEV API dw_event_new(void) -{ - HEV blah; - - if(DosCreateEventSem (NULL, &blah, 0L, FALSE)) - return 0; - - return blah; -} - -/* - * Resets a semaphore created by dw_event_new(). - * Parameters: - * eve: The handle to the event returned by dw_event_new(). - */ -int API dw_event_reset(HEV eve) -{ - ULONG count; - - if(DosResetEventSem(eve, &count)) - return FALSE; - return TRUE; -} - -/* - * Posts a semaphore created by dw_event_new(). Causing all threads - * waiting on this event in dw_event_wait to continue. - * Parameters: - * eve: The handle to the event returned by dw_event_new(). - */ -int API dw_event_post(HEV eve) -{ - if(DosPostEventSem(eve)) - return FALSE; - return TRUE; -} - - -/* - * Waits on a semaphore created by dw_event_new(), until the - * event gets posted or until the timeout expires. - * Parameters: - * eve: The handle to the event returned by dw_event_new(). - */ -int API dw_event_wait(HEV eve, unsigned long timeout) -{ - int rc = DosWaitEventSem(eve, timeout); - if(!rc) - return 1; - if(rc == ERROR_TIMEOUT) - return -1; - return 0; -} - -/* - * Closes a semaphore created by dw_event_new(). - * Parameters: - * eve: The handle to the event returned by dw_event_new(). - */ -int API dw_event_close(HEV *eve) -{ - if(!eve || ~DosCloseEventSem(*eve)) - return FALSE; - return TRUE; -} - -/* - * Encapsulate the message queues on OS/2. - */ -void _dwthreadstart(void *data) -{ - HAB thishab = WinInitialize(0); - HMQ thishmq = WinCreateMsgQueue(dwhab, 0); - void (*threadfunc)(void *) = NULL; - void **tmp = (void **)data; - - threadfunc = (void (*)(void *))tmp[0]; - threadfunc(tmp[1]); - - free(tmp); - - WinDestroyMsgQueue(thishmq); - WinTerminate(thishab); -} - -/* - * Creates a new thread with a starting point of func. - * Parameters: - * func: Function which will be run in the new thread. - * data: Parameter(s) passed to the function. - * stack: Stack size of new thread (OS/2 and Windows only). - */ -DWTID API dw_thread_new(void *func, void *data, int stack) -{ - void **tmp = malloc(sizeof(void *) * 2); - - tmp[0] = func; - tmp[1] = data; - - return (DWTID)_beginthread((void (*)(void *))_dwthreadstart, NULL, stack, (void *)tmp); -} - -/* - * Ends execution of current thread immediately. - */ -void API dw_thread_end(void) -{ - _endthread(); -} - -/* - * Returns the current thread's ID. - */ -DWTID API dw_thread_id(void) -{ - return (DWTID)_threadid; -} - -/* - * 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) -{ - /* Destroy the menu message window */ - dw_window_destroy(hwndApp); - - /* In case we are in a signal handler, don't - * try to free memory that could possibly be - * free()'d by the runtime already. - */ - Root = NULL; - - exit(exitcode); -} - -/* - * Creates a splitbar window (widget) with given parameters. - * Parameters: - * type: Value can be DW_VERT or DW_HORZ. - * topleft: Handle to the window to be top or left. - * bottomright: Handle to the window to be bottom or right. - * Returns: - * A handle to a splitbar window or NULL on failure. - */ -HWND API dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id) -{ - HWND tmp = WinCreateWindow(HWND_OBJECT, - SplitbarClassName, - NULL, - WS_VISIBLE | WS_CLIPCHILDREN, - 0,0,2000,1000, - NULLHANDLE, - HWND_TOP, - id, - NULL, - NULL); - if(tmp) - { - HWND tmpbox = dw_box_new(DW_VERT, 0); - float *percent = malloc(sizeof(float)); - - dw_box_pack_start(tmpbox, topleft, 1, 1, TRUE, TRUE, 0); - WinSetParent(tmpbox, tmp, FALSE); - dw_window_set_data(tmp, "_dw_topleft", (void *)tmpbox); - - tmpbox = dw_box_new(DW_VERT, 0); - dw_box_pack_start(tmpbox, bottomright, 1, 1, TRUE, TRUE, 0); - WinSetParent(tmpbox, tmp, FALSE); - *percent = 50.0; - dw_window_set_data(tmp, "_dw_bottomright", (void *)tmpbox); - dw_window_set_data(tmp, "_dw_percent", (void *)percent); - dw_window_set_data(tmp, "_dw_type", (void *)type); - } - return tmp; -} - -/* - * Sets the position of a splitbar (pecentage). - * Parameters: - * handle: The handle to the splitbar returned by dw_splitbar_new(). - */ -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; - - if(mypercent) - *mypercent = percent; - - dw_window_get_pos_size(handle, NULL, NULL, &width, &height); - - _handle_splitbar_resize(handle, percent, type, width, height); -} - -/* - * Gets the position of a splitbar (pecentage). - * Parameters: - * handle: The handle to the splitbar returned by dw_splitbar_new(). - */ -float API dw_splitbar_get(HWND handle) -{ - float *percent = (float *)dw_window_get_data(handle, "_dw_percent"); - - if(percent) - return *percent; - return 0.0; -} - -/* - * Pack windows (widgets) into a box from the start (or top). - * Parameters: - * box: Window handle of the box to be packed into. - * item: Window handle of the item to be back. - * width: Width in pixels of the item or -1 to be self determined. - * height: Height in pixels of the item or -1 to be self determined. - * hsize: TRUE if the window (widget) should expand horizontally to fill space given. - * vsize: TRUE if the window (widget) should expand vertically to fill space given. - * pad: Number of pixels of padding around the item. - */ -void API dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) -{ - Box *thisbox; - char *funcname = "dw_box_pack_start()"; - - /* - * If you try and pack an item into itself VERY bad things can happen; like at least an - * infinite loop on GTK! Lets be safe! - */ - if(box == item) - { - dw_messagebox(funcname, DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!",box,item); - return; - } - - if(WinWindowFromID(box, FID_CLIENT)) - { - box = WinWindowFromID(box, FID_CLIENT); - thisbox = WinQueryWindowPtr(box, QWP_USER); - hsize = TRUE; - vsize = TRUE; - } - else - thisbox = WinQueryWindowPtr(box, QWP_USER); - if(thisbox) - { - if(thisbox->type == DW_HORZ) - _dw_box_pack_end(box, item, width, height, hsize, vsize, pad, funcname); - else - _dw_box_pack_start(box, item, width, height, hsize, vsize, pad, funcname); - } -} - -void _dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad, char *functionname) -{ - Box *thisbox = WinQueryWindowPtr(box, QWP_USER); - - if(thisbox) - { - int z; - Item *tmpitem, *thisitem = thisbox->items; - char tmpbuf[100]; - HWND frame = (HWND)dw_window_get_data(item, "_dw_combo_box"); - - tmpitem = malloc(sizeof(Item)*(thisbox->count+1)); - - for(z=0;z<thisbox->count;z++) - { - tmpitem[z+1] = thisitem[z]; - } - - WinQueryClassName(item, 99, tmpbuf); - - if(vsize && !height) - height = 1; - if(hsize && !width) - width = 1; - - if(strncmp(tmpbuf, "#1", 3)==0) - tmpitem[0].type = TYPEBOX; - else - { - if ( width == 0 && hsize == FALSE ) - dw_messagebox(functionname, DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item); - if ( height == 0 && vsize == FALSE ) - dw_messagebox(functionname, DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item); - - tmpitem[0].type = TYPEITEM; - } - - tmpitem[0].hwnd = item; - tmpitem[0].origwidth = tmpitem[0].width = width; - tmpitem[0].origheight = tmpitem[0].height = height; - tmpitem[0].pad = pad; - if(hsize) - tmpitem[0].hsize = SIZEEXPAND; - else - tmpitem[0].hsize = SIZESTATIC; - - if(vsize) - tmpitem[0].vsize = SIZEEXPAND; - else - tmpitem[0].vsize = SIZESTATIC; - - thisbox->items = tmpitem; - - if(thisbox->count) - free(thisitem); - - thisbox->count++; - - WinQueryClassName(item, 99, tmpbuf); - /* Don't set the ownership if it's an entryfield or spinbutton */ - if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 4)!=0 && strncmp(tmpbuf, "#2", 3)!=0) - WinSetOwner(item, box); - WinSetParent(frame ? frame : item, box, FALSE); - } -} - -/* The following two functions graciously contributed by Peter Nielsen. */ -static ULONG _ParseBuildLevel (char* pchBuffer, ULONG ulSize) { - char* pchStart = pchBuffer; - char* pchEnd = pchStart + ulSize - 2; - - while (pchEnd >= pchStart) - { - if ((pchEnd[0] == '#') && (pchEnd[1] == '@')) - { - *pchEnd-- = '\0'; - while (pchEnd >= pchStart) - { - if ((pchEnd[0] == '@') && (pchEnd[1] == '#')) - { - ULONG ulMajor = 0; - ULONG ulMinor = 0; - - char* pch = pchEnd + 2; - while (!isdigit ((int)*pch) && *pch) - pch++; - - while (isdigit ((int)*pch)) - ulMajor = ulMajor * 10 + *pch++ - '0'; - - if (*pch == '.') - { - while (isdigit ((int)*++pch)) - ulMinor = ulMinor * 10 + *pch - '0'; - } - return ((ulMajor << 16) | ulMinor); - } - pchEnd--; - } - } - pchEnd--; - } - return (0); -} - -ULONG _GetSystemBuildLevel(void) { - /* The build level info is normally available in the end of the OS2KRNL file. However, this is not the case in some beta versions of OS/2. - * We first try to find the info in the 256 last bytes of the file. If that fails, we load the entire file and search it completely. - */ - ULONG ulBootDrive = 0; - ULONG ulBuild = 0; - if (DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive, sizeof (ulBootDrive)) == NO_ERROR) - { - char achFileName[11] = "C:\\OS2KRNL"; - HFILE hfile; - ULONG ulResult; - - achFileName[0] = (char)('A'+ulBootDrive-1); - - if (DosOpen (achFileName, &hfile, &ulResult, 0, 0, OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL) == NO_ERROR) - { - ULONG ulFileSize = 0; - if (DosSetFilePtr (hfile, 0, FILE_END, &ulFileSize) == NO_ERROR) - { - const ULONG ulFirstTry = min (256, ulFileSize); - if (DosSetFilePtr (hfile, -(LONG)ulFirstTry, FILE_END, &ulResult) == NO_ERROR) - { - char *pchBuffer = malloc(ulFirstTry); - if (DosRead (hfile, pchBuffer, ulFirstTry, &ulResult) == NO_ERROR) - { - ulBuild = _ParseBuildLevel (pchBuffer, ulFirstTry); - if (ulBuild == 0) - { - if (DosSetFilePtr (hfile, 0, FILE_BEGIN, &ulResult) == NO_ERROR) - { - free(pchBuffer); - pchBuffer = malloc(ulFileSize); - - if (DosRead (hfile, pchBuffer, ulFileSize, &ulResult) == NO_ERROR) - ulBuild = _ParseBuildLevel (pchBuffer, ulFileSize); - } - } - } - free(pchBuffer); - } - } - DosClose (hfile); - } - } - return (ulBuild); -} - -/* - * Sets the default focus item for a window/dialog. - * Parameters: - * window: Toplevel window or dialog. - * defaultitem: Handle to the dialog item to be default. - */ -void API dw_window_default(HWND window, HWND defaultitem) -{ - Box *thisbox = NULL; - HWND box; - - box = WinWindowFromID(window, FID_CLIENT); - if(box) - thisbox = WinQueryWindowPtr(box, QWP_USER); - - if(thisbox) - thisbox->defaultitem = defaultitem; -} - -/* - * Sets window to click the default dialog item when an ENTER is pressed. - * Parameters: - * window: Window (widget) to look for the ENTER press. - * next: Window (widget) to move to next (or click) - */ -void API dw_window_click_default(HWND window, HWND next) -{ - WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER); - - if(blah) - blah->clickdefault = next; -} - -/* - * Returns some information about the current operating environment. - * Parameters: - * env: Pointer to a DWEnv struct. - */ -void API dw_environment_query(DWEnv *env) -{ - ULONG Build; - - if(!env) - return; - - /* The default is OS/2 2.0 */ - strcpy(env->osName,"OS/2"); - env->MajorVersion = 2; - env->MinorVersion = 0; - - Build = _GetSystemBuildLevel(); - env->MinorBuild = Build & 0xFFFF; - env->MajorBuild = Build >> 16; - - if (aulBuffer[0] == 20) - { - int i = (unsigned int)aulBuffer[1]; - if (i > 20) - { - strcpy(env->osName,"Warp"); - env->MajorVersion = (int)i/10; - env->MinorVersion = i-(((int)i/10)*10); - } - else if (i == 10) - env->MinorVersion = 1; - } - strcpy(env->buildDate, __DATE__); - strcpy(env->buildTime, __TIME__); - env->DWMajorVersion = DW_MAJOR_VERSION; - env->DWMinorVersion = DW_MINOR_VERSION; - env->DWSubVersion = DW_SUB_VERSION; -} - -/* The next few functions are support functions for the OS/2 folder browser */ -void _populate_directory(HWND tree, HTREEITEM parent, char *path) -{ - FILEFINDBUF3 ffbuf; - HTREEITEM item; - ULONG count = 1; - HDIR hdir = HDIR_CREATE; - - if(DosFindFirst(path, &hdir, FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_ARCHIVED | MUST_HAVE_DIRECTORY, - &ffbuf, sizeof(FILEFINDBUF3), &count, FIL_STANDARD) == NO_ERROR) - { - while(DosFindNext(hdir, &ffbuf, sizeof(FILEFINDBUF3), &count) == NO_ERROR) - { - if(strcmp(ffbuf.achName, ".") && strcmp(ffbuf.achName, "..")) - { - int len = strlen(path); - char *folder = malloc(len + ffbuf.cchName + 2); - HTREEITEM tempitem; - - strcpy(folder, path); - strcpy(&folder[len-1], ffbuf.achName); - - item = dw_tree_insert(tree, ffbuf.achName, WinLoadFileIcon(folder, TRUE), parent, (void *)parent); - tempitem = dw_tree_insert(tree, "", 0, item, 0); - dw_tree_set_data(tree, item, (void *)tempitem); - } - } - DosFindClose(hdir); - } -} - -void _populate_tree_thread(void *data) -{ - HWND window = (HWND)data, tree = (HWND)dw_window_get_data(window, "_dw_tree"); - HMTX mtx = (HMTX)dw_window_get_data(window, "_dw_mutex"); - int drive; - HTREEITEM items[26]; - FSINFO volinfo; - - DosError(FERR_DISABLEHARDERR); - - dw_mutex_lock(mtx); - for(drive=0;drive<26;drive++) - { - if(DosQueryFSInfo(drive+1, FSIL_VOLSER,(PVOID)&volinfo, sizeof(FSINFO)) == NO_ERROR) - { - char folder[5] = "C:\\", name[9] = "Drive C:"; - HTREEITEM tempitem; - - folder[0] = name[6] = 'A' + drive; - - items[drive] = dw_tree_insert(tree, name, WinLoadFileIcon(folder, TRUE), NULL, 0); - tempitem = dw_tree_insert(tree, "", 0, items[drive], 0); - dw_tree_set_data(tree, items[drive], (void *)tempitem); - } - else - items[drive] = 0; - } - dw_mutex_unlock(mtx); - - DosError(FERR_ENABLEHARDERR); -} - -int DWSIGNAL _dw_ok_func(HWND window, void *data) -{ - DWDialog *dwwait = (DWDialog *)data; - HMTX mtx = (HMTX)dw_window_get_data((HWND)dwwait->data, "_dw_mutex"); - void *treedata; - - window = window; - if(!dwwait) - return FALSE; - - dw_mutex_lock(mtx); - treedata = dw_window_get_data((HWND)dwwait->data, "_dw_tree_selected"); - dw_mutex_close(mtx); - dw_window_destroy((HWND)dwwait->data); - dw_dialog_dismiss((DWDialog *)data, treedata); - return FALSE; -} - -int DWSIGNAL _dw_cancel_func(HWND window, void *data) -{ - DWDialog *dwwait = (DWDialog *)data; - HMTX mtx = (HMTX)dw_window_get_data((HWND)dwwait->data, "_dw_mutex"); - - window = window; - if(!dwwait) - return FALSE; - - dw_mutex_lock(mtx); - dw_mutex_close(mtx); - dw_window_destroy((HWND)dwwait->data); - dw_dialog_dismiss((DWDialog *)data, NULL); - return FALSE; -} - -char *_tree_folder(HWND tree, HTREEITEM item) -{ - char *folder=strdup(""); - HTREEITEM parent = item; - - while(parent) - { - char *temp, *text = dw_tree_get_title(tree, parent); - - if(text) - { - if(strncmp(text, "Drive ", 6) == 0) - text = &text[6]; - - temp = malloc(strlen(text) + strlen(folder) + 3); - strcpy(temp, text); - strcat(temp, "\\"); - strcat(temp, folder); - free(folder); - folder = temp; - } - parent = dw_tree_get_parent(tree, parent); - } - return folder; -} - -int DWSIGNAL _item_select(HWND window, HTREEITEM item, char *text, void *data, void *itemdata) -{ - DWDialog *dwwait = (DWDialog *)data; - char *treedata = (char *)dw_window_get_data((HWND)dwwait->data, "_dw_tree_selected"); - - text = text; itemdata = itemdata; - if(treedata) - free(treedata); - - treedata = _tree_folder(window, item); - dw_window_set_data((HWND)dwwait->data, "_dw_tree_selected", (void *)treedata); - - return FALSE; -} - -int DWSIGNAL _tree_expand(HWND window, HTREEITEM item, void *data) -{ - HTREEITEM tempitem = (HTREEITEM)dw_tree_get_data(window, item); - - data = data; - if(tempitem) - { - char *folder = _tree_folder(window, item); - - dw_tree_set_data(window, item, 0); - dw_tree_delete(window, tempitem); - - if(*folder) - { - strcat(folder, "*"); - _populate_directory(window, item, folder); - } - free(folder); - } - - return FALSE; -} - -/* - * Opens a file dialog and queries user selection. - * Parameters: - * title: Title bar text for dialog. - * defpath: The default path of the open dialog. - * ext: Default file extention. - * flags: DW_FILE_OPEN or DW_FILE_SAVE. - * Returns: - * NULL on error. A malloced buffer containing - * the file path on success. - * - */ -char * API dw_file_browse(char *title, char *defpath, char *ext, int flags) -{ - if(flags == DW_DIRECTORY_OPEN) - { - HWND window, hbox, vbox, tree, button; - DWDialog *dwwait; - HMTX mtx = dw_mutex_new(); - - window = dw_window_new( HWND_DESKTOP, title, FCF_SHELLPOSITION | FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX); - - vbox = dw_box_new(DW_VERT, 5); - - dw_box_pack_start(window, vbox, 0, 0, TRUE, TRUE, 0); - - tree = dw_tree_new(60); - - dw_box_pack_start(vbox, tree, 1, 1, TRUE, TRUE, 0); - dw_window_set_data(window, "_dw_mutex", (void *)mtx); - dw_window_set_data(window, "_dw_tree", (void *)tree); - - hbox = dw_box_new(DW_HORZ, 0); - - dw_box_pack_start(vbox, hbox, 0, 0, TRUE, FALSE, 0); - - dwwait = dw_dialog_new((void *)window); - - dw_signal_connect(tree, DW_SIGNAL_ITEM_SELECT, DW_SIGNAL_FUNC(_item_select), (void *)dwwait); - dw_signal_connect(tree, DW_SIGNAL_TREE_EXPAND, DW_SIGNAL_FUNC(_tree_expand), (void *)dwwait); - - button = dw_button_new("Ok", 1001L); - dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3); - dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_ok_func), (void *)dwwait); - - button = dw_button_new("Cancel", 1002L); - dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3); - dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_cancel_func), (void *)dwwait); - - dw_window_set_usize(window, 225, 300); - dw_window_show(window); - - dw_thread_new((void *)_populate_tree_thread, (void *)window, 0xff); - return (char *)dw_dialog_wait(dwwait); - } - else - { - FILEDLG fild; - HWND hwndFile; - int len; - - if(defpath) - strcpy(fild.szFullFile, defpath); - else - strcpy(fild.szFullFile, ""); - - len = strlen(fild.szFullFile); - - if(len) - { - if(fild.szFullFile[len-1] != '\\') - strcat(fild.szFullFile, "\\"); - } - strcat(fild.szFullFile, "*"); - - if(ext) - { - strcat(fild.szFullFile, "."); - strcat(fild.szFullFile, ext); - } - - memset(&fild, 0, sizeof(FILEDLG)); - fild.cbSize = sizeof(FILEDLG); - fild.fl = FDS_CENTER | FDS_OPEN_DIALOG; - fild.pszTitle = title; - fild.pszOKButton = ((flags & DW_FILE_SAVE) ? "Save" : "Open"); - fild.pfnDlgProc = (PFNWP)WinDefFileDlgProc; - - hwndFile = WinFileDlg(HWND_DESKTOP, HWND_DESKTOP, &fild); - if(hwndFile) - { - switch(fild.lReturn) - { - case DID_OK: - return strdup(fild.szFullFile); - case DID_CANCEL: - return NULL; - } - } - } - return NULL; -} - -/* Internal function to set drive and directory */ -int _SetPath(char *path) -{ -#ifndef __WATCOMC__ - if(strlen(path) > 2) - { - if(path[1] == ':') - { - char drive = toupper(path[0]); - _chdrive((drive - 'A')+1); - } - } -#endif - return chdir(path); -} - -/* - * Execute and external program in a seperate session. - * Parameters: - * program: Program name with optional path. - * type: Either DW_EXEC_CON or DW_EXEC_GUI. - * params: An array of pointers to string arguements. - * Returns: - * -1 on error. - */ -int API dw_exec(char *program, int type, char **params) -{ - type = type; /* keep compiler happy */ - return spawnvp(P_NOWAIT, program, (const char **)params); -} - -/* - * Loads a web browser pointed at the given URL. - * Parameters: - * url: Uniform resource locator. - */ -int API dw_browse(char *url) -{ - char *execargs[3], browser[1024], *olddir, *newurl = NULL; - int len, ret; - - olddir = _getcwd(NULL, 1024); - - PrfQueryProfileString(HINI_USERPROFILE, "WPURLDEFAULTSETTINGS", - "DefaultWorkingDir", NULL, browser, 1024); - - if(browser[0]) - _SetPath(browser); - - PrfQueryProfileString(HINI_USERPROFILE, "WPURLDEFAULTSETTINGS", - "DefaultBrowserExe", NULL, browser, 1024); - - len = strlen(browser) - strlen("explore.exe"); - - execargs[0] = browser; - execargs[1] = url; - execargs[2] = NULL; - - /* Special case for Web Explorer, it requires file:/// instead - * of file:// so I am handling it here. - */ - if(len > 0) - { - if(stricmp(&browser[len], "explore.exe") == 0 && stricmp(url, "file://") == 0) - { - int newlen, z; - newurl = malloc(strlen(url) + 2); - sprintf(newurl, "file:///%s", &url[7]); - newlen = strlen(newurl); - for(z=8;z<(newlen-8);z++) - { - if(newurl[z] == '|') - newurl[z] = ':'; - if(newurl[z] == '/') - newurl[z] = '\\'; - } - execargs[1] = newurl; - } - } - - ret = dw_exec(browser, DW_EXEC_GUI, execargs); - - if(olddir) - { - _SetPath(olddir); - free(olddir); - } - if(newurl) - free(newurl); - return ret; -} - -/* - * Returns a pointer to a static buffer which containes the - * current user directory. Or the root directory (C:\ on - * OS/2 and Windows). - */ -char * API dw_user_dir(void) -{ - static char _user_dir[1024] = ""; - - if(!_user_dir[0]) - { - char *home = getenv("HOME"); - - if(home) - strcpy(_user_dir, home); - else - strcpy(_user_dir, "C:\\"); - } - return _user_dir; -} - -/* - * Call a function from the window (widget)'s context. - * Parameters: - * handle: Window handle of the widget. - * function: Function pointer to be called. - * data: Pointer to the data to be passed to the function. - */ -void API dw_window_function(HWND handle, void *function, void *data) -{ - WinSendMsg(handle, WM_USER, (MPARAM)function, (MPARAM)data); -} - -/* Functions for managing the user data lists that are associated with - * a given window handle. Used in dw_window_set_data() and - * dw_window_get_data(). - */ -UserData *_find_userdata(UserData **root, char *varname) -{ - UserData *tmp = *root; - - while(tmp) - { - if(stricmp(tmp->varname, varname) == 0) - return tmp; - tmp = tmp->next; - } - return NULL; -} - -int _new_userdata(UserData **root, char *varname, void *data) -{ - UserData *new = _find_userdata(root, varname); - - if(new) - { - new->data = data; - return TRUE; - } - else - { - new = malloc(sizeof(UserData)); - if(new) - { - new->varname = strdup(varname); - new->data = data; - - new->next = NULL; - - if (!*root) - *root = new; - else - { - UserData *prev = NULL, *tmp = *root; - while(tmp) - { - prev = tmp; - tmp = tmp->next; - } - if(prev) - prev->next = new; - else - *root = new; - } - return TRUE; - } - } - return FALSE; -} - -int _remove_userdata(UserData **root, char *varname, int all) -{ - UserData *prev = NULL, *tmp = *root; - - while(tmp) - { - if(all || stricmp(tmp->varname, varname) == 0) - { - if(!prev) - { - *root = tmp->next; - free(tmp->varname); - free(tmp); - if(!all) - return 0; - tmp = *root; - } - else - { - /* If all is true we should - * never get here. - */ - prev->next = tmp->next; - free(tmp->varname); - free(tmp); - return 0; - } - } - else - { - prev = tmp; - tmp = tmp->next; - } - } - return 0; -} - -/* - * Add a named user data item to a window handle. - * Parameters: - * window: Window handle of signal to be called back. - * dataname: A string pointer identifying which signal to be hooked. - * data: User data to be passed to the handler function. - */ -void API dw_window_set_data(HWND window, char *dataname, void *data) -{ - WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER); - - if(!blah) - { - if(!dataname) - return; - - blah = calloc(1, sizeof(WindowData)); - WinSetWindowPtr(window, QWP_USER, blah); - } - - if(data) - _new_userdata(&(blah->root), dataname, data); - else - { - if(dataname) - _remove_userdata(&(blah->root), dataname, FALSE); - else - _remove_userdata(&(blah->root), NULL, TRUE); - } -} - -/* - * Gets a named user data item to a window handle. - * Parameters: - * window: Window handle of signal to be called back. - * dataname: A string pointer identifying which signal to be hooked. - * data: User data to be passed to the handler function. - */ -void *dw_window_get_data(HWND window, char *dataname) -{ - WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER); - - if(blah && blah->root && dataname) - { - UserData *ud = _find_userdata(&(blah->root), dataname); - if(ud) - return ud->data; - } - return NULL; -} - -/* - * Add a callback to a timer event. - * Parameters: - * interval: Milliseconds to delay between calls. - * sigfunc: The pointer to the function to be used as the callback. - * data: User data to be passed to the handler function. - * Returns: - * Timer ID for use with dw_timer_disconnect(), 0 on error. - */ -int API dw_timer_connect(int interval, void *sigfunc, void *data) -{ - if(sigfunc) - { - int timerid = WinStartTimer(dwhab, NULLHANDLE, 0, interval); - - if(timerid) - { - _new_signal(WM_TIMER, NULLHANDLE, timerid, sigfunc, data); - return timerid; - } - } - return 0; -} - -/* - * Removes timer callback. - * Parameters: - * id: Timer ID returned by dw_timer_connect(). - */ -void API dw_timer_disconnect(int id) -{ - SignalHandler *prev = NULL, *tmp = Root; - - /* 0 is an invalid timer ID */ - if(!id) - return; - - WinStopTimer(dwhab, NULLHANDLE, id); - - while(tmp) - { - if(tmp->id == id) - { - if(prev) - { - prev->next = tmp->next; - free(tmp); - tmp = prev->next; - } - else - { - Root = tmp->next; - free(tmp); - tmp = Root; - } - } - else - { - prev = tmp; - tmp = tmp->next; - } - } -} - -/* - * Add a callback to a window event. - * 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. - * data: User data to be passed to the handler function. - */ -void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data) -{ - ULONG message = 0, id = 0; - - if(window && signame && sigfunc) - { - if((message = _findsigmessage(signame)) != 0) - { - /* Handle special case of the menu item */ - if(message == WM_COMMAND && window < 65536) - { - char buffer[15]; - HWND owner; - - sprintf(buffer, "_dw_id%d", (int)window); - owner = (HWND)dw_window_get_data(hwndApp, buffer); - - if(owner) - { - id = window; - window = owner; - dw_window_set_data(hwndApp, buffer, 0); - } - else - { - /* If it is a popup menu clear all entries */ - dw_signal_disconnect_by_window(window); - } - } - _new_signal(message, window, id, sigfunc, data); - } - } -} - -/* - * Removes callbacks for a given window with given name. - * Parameters: - * window: Window handle of callback to be removed. - */ -void API dw_signal_disconnect_by_name(HWND window, char *signame) -{ - SignalHandler *prev = NULL, *tmp = Root; - ULONG message; - - if(!window || !signame || (message = _findsigmessage(signame)) == 0) - return; - - while(tmp) - { - if(tmp->window == window && tmp->message == message) - { - if(prev) - { - prev->next = tmp->next; - free(tmp); - tmp = prev->next; - } - else - { - Root = tmp->next; - free(tmp); - tmp = Root; - } - } - else - { - prev = tmp; - tmp = tmp->next; - } - } -} - -/* - * Removes all callbacks for a given window. - * Parameters: - * window: Window handle of callback to be removed. - */ -void API dw_signal_disconnect_by_window(HWND window) -{ - SignalHandler *prev = NULL, *tmp = Root; - - while(tmp) - { - if(tmp->window == window) - { - if(prev) - { - prev->next = tmp->next; - free(tmp); - tmp = prev->next; - } - else - { - Root = tmp->next; - free(tmp); - tmp = Root; - } - } - else - { - prev = tmp; - tmp = tmp->next; - } - } -} - -/* - * Removes all callbacks for a given window with specified data. - * Parameters: - * window: Window handle of callback to be removed. - * data: Pointer to the data to be compared against. - */ -void API dw_signal_disconnect_by_data(HWND window, void *data) -{ - SignalHandler *prev = NULL, *tmp = Root; - - while(tmp) - { - if(tmp->window == window && tmp->data == data) - { - if(prev) - { - prev->next = tmp->next; - free(tmp); - tmp = prev->next; - } - else - { - Root = tmp->next; - free(tmp); - tmp = Root; - } - } - else - { - prev = tmp; - tmp = tmp->next; - } - } -} - - +/* + * Dynamic Windows: + * A GTK like implementation of the PM GUI + * + * (C) 2000-2011 Brian Smith <brian@dbsoft.org> + * (C) 2003-2008 Mark Hessling <m.hessling@qut.edu.au> + * (C) 2000 Achim Hasenmueller <achimha@innotek.de> + * (C) 2000 Peter Nielsen <peter@pmview.com> + * (C) 1998 Sergey I. Yevtushenko (some code borrowed from cell toolkit) + * + */ +#define INCL_DOS +#define INCL_DOSERRORS +#define INCL_WIN +#define INCL_GPI +#define INCL_DEV +#define INCL_SPL +#define INCL_SPLDOSPRINT +#define INCL_SPLERRORS + +#include <os2.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <stddef.h> +#include <ctype.h> +#include <process.h> +#include <time.h> +#include <io.h> +#include <math.h> +#ifndef __EMX__ +#include <direct.h> +#endif +#include <sys/time.h> +#include <sys/stat.h> +#include "dw.h" + +#define QWP_USER 0 + +/* The toolkit headers don't seem to have this */ +BOOL APIENTRY WinStretchPointer(HPS hps, LONG x, LONG y, LONG cx, LONG cy, HPOINTER hptr, ULONG fs); + +MRESULT EXPENTRY _run_event(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2); +MRESULT EXPENTRY _wndproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2); +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); +void _dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad, char *functionname); +void _dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad, char *functionname); +void _free_menu_data(HWND menu); + +char ClassName[] = "dynamicwindows"; +char SplitbarClassName[] = "dwsplitbar"; +char ScrollClassName[] = "dwscroll"; +char *DefaultFont = "9.WarpSans"; + +HAB dwhab = 0; +HMQ dwhmq = 0; +DWTID _dwtid = 0; +LONG _foreground = 0xAAAAAA, _background = DW_CLR_DEFAULT; + +HWND hwndApp = NULLHANDLE, hwndBubble = NULLHANDLE, hwndBubbleLast = NULLHANDLE, hwndEmph = NULLHANDLE; +HWND hwndTrayServer = NULLHANDLE, hwndTaskBar = NULLHANDLE; +; +PRECORDCORE pCoreEmph = NULL; +ULONG aulBuffer[4]; +HWND lasthcnr = 0, lastitem = 0, popup = 0, desktop; +HMOD wpconfig = 0; + +unsigned long _colors[] = { + CLR_BLACK, + CLR_DARKRED, + CLR_DARKGREEN, + CLR_BROWN, + CLR_DARKBLUE, + CLR_DARKPINK, + CLR_DARKCYAN, + CLR_PALEGRAY, + CLR_DARKGRAY, + CLR_RED, + CLR_GREEN, + CLR_YELLOW, + CLR_BLUE, + CLR_PINK, + CLR_CYAN, + CLR_WHITE +}; + +#define IS_WARP4() (aulBuffer[0] == 20 && aulBuffer[1] >= 40) + +#ifndef min +#define min(a, b) (((a < b) ? a : b)) +#endif + +typedef struct _sighandler +{ + struct _sighandler *next; + ULONG message; + HWND window; + int id; + void *signalfunction; + void *data; + +} SignalHandler; + +SignalHandler *Root = NULL; + +typedef struct +{ + ULONG message; + char name[30]; + +} SignalList; + +/* List of signals and their equivilent OS/2 message */ +#define SIGNALMAX 16 + +SignalList SignalTranslate[SIGNALMAX] = { + { WM_SIZE, DW_SIGNAL_CONFIGURE }, + { WM_CHAR, DW_SIGNAL_KEY_PRESS }, + { WM_BUTTON1DOWN, DW_SIGNAL_BUTTON_PRESS }, + { WM_BUTTON1UP, DW_SIGNAL_BUTTON_RELEASE }, + { WM_MOUSEMOVE, DW_SIGNAL_MOTION_NOTIFY }, + { WM_CLOSE, DW_SIGNAL_DELETE }, + { WM_PAINT, DW_SIGNAL_EXPOSE }, + { WM_COMMAND, DW_SIGNAL_CLICKED }, + { CN_ENTER, DW_SIGNAL_ITEM_ENTER }, + { CN_CONTEXTMENU, DW_SIGNAL_ITEM_CONTEXT }, + { LN_SELECT, DW_SIGNAL_LIST_SELECT }, + { CN_EMPHASIS, DW_SIGNAL_ITEM_SELECT }, + { WM_SETFOCUS, DW_SIGNAL_SET_FOCUS }, + { SLN_SLIDERTRACK, DW_SIGNAL_VALUE_CHANGED }, + { BKN_PAGESELECTED,DW_SIGNAL_SWITCH_PAGE }, + { CN_EXPANDTREE, DW_SIGNAL_TREE_EXPAND } +}; + +/* Internal function to keep a semi-unique ID within valid range */ +USHORT _GlobalID(void) +{ + static USHORT GlobalID = 9999; + + GlobalID++; + if(GlobalID >= 65534) + { + GlobalID = 10000; + } + return GlobalID; +} + +/* This function adds a signal handler callback into the linked list. + */ +void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data) +{ + SignalHandler *new = malloc(sizeof(SignalHandler)); + + new->message = message; + new->window = window; + new->id = id; + new->signalfunction = signalfunction; + new->data = data; + new->next = NULL; + + if (!Root) + Root = new; + else + { + SignalHandler *prev = NULL, *tmp = Root; + while(tmp) + { + if(tmp->message == message && + tmp->window == window && + tmp->id == id && + tmp->signalfunction == signalfunction) + { + tmp->data = data; + free(new); + return; + } + prev = tmp; + tmp = tmp->next; + } + if(prev) + prev->next = new; + else + Root = new; + } +} + +/* Finds the message number for a given signal name */ +ULONG _findsigmessage(char *signame) +{ + int z; + + for(z=0;z<SIGNALMAX;z++) + { + if(stricmp(signame, SignalTranslate[z].name) == 0) + return SignalTranslate[z].message; + } + return 0L; +} + +typedef struct _CNRITEM +{ + MINIRECORDCORE rc; + HPOINTER hptrIcon; + PVOID user; + HTREEITEM parent; + +} CNRITEM, *PCNRITEM; + + +int _null_key(HWND window, int key, void *data) +{ + window = window; /* keep compiler happy */ + key = key; /* keep compiler happy */ + data = data; /* keep compiler happy */ + return TRUE; +} + +/* Find the desktop window handle */ +HWND _toplevel_window(HWND handle) +{ + HWND box, lastbox = WinQueryWindow(handle, QW_PARENT); + + /* Find the toplevel window */ + while((box = WinQueryWindow(lastbox, QW_PARENT)) != desktop && box > 0) + { + lastbox = box; + } + if(box > 0) + return lastbox; + return handle; +} + + +/* Returns height of specified window. */ +int _get_height(HWND handle) +{ + unsigned long height; + dw_window_get_pos_size(handle, NULL, NULL, NULL, &height); + return (int)height; +} + +/* Find the height of the frame a desktop style window is sitting on */ +int _get_frame_height(HWND handle) +{ + while(handle) + { + HWND client; + if((client = WinWindowFromID(handle, FID_CLIENT)) != NULLHANDLE) + { + return _get_height(WinQueryWindow(handle, QW_PARENT)); + } + handle = WinQueryWindow(handle, QW_PARENT); + } + return dw_screen_height(); +} + +/* A "safe" WinSendMsg() that tries multiple times in case the + * queue is blocked for one reason or another. + */ +MRESULT _dw_send_msg(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2, int failure) +{ + MRESULT res; + int z = 0; + + while((int)(res = WinSendMsg(hwnd, msg, mp1, mp2)) == failure) + { + z++; + if(z > 5000000) + return (MRESULT)failure; + dw_main_sleep(1); + } + return res; +} + +/* Used in the slider and percent classes internally */ +unsigned int _dw_percent_get_range(HWND handle) +{ + return SHORT2FROMMP(WinSendMsg(handle, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), 0)); +} + +/* Return the entryfield child of a window */ +HWND _find_entryfield(HWND handle) +{ + HENUM henum; + HWND child, entry = 0; + + henum = WinBeginEnumWindows(handle); + while((child = WinGetNextWindow(henum)) != NULLHANDLE) + { + char tmpbuf[100]; + + WinQueryClassName(child, 99, tmpbuf); + + if(strncmp(tmpbuf, "#6", 3)==0) /* Entryfield */ + { + entry = child; + break; + } + } + WinEndEnumWindows(henum); + return entry; +} + +/* This function changes the owner of buttons in to the + * dynamicwindows handle to fix a problem in notebooks. + */ +void _fix_button_owner(HWND handle, HWND dw) +{ + HENUM henum; + HWND child; + + henum = WinBeginEnumWindows(handle); + while((child = WinGetNextWindow(henum)) != NULLHANDLE) + { + char tmpbuf[100]; + + WinQueryClassName(child, 99, tmpbuf); + + if(strncmp(tmpbuf, "#3", 3)==0 && dw) /* Button */ + WinSetOwner(child, dw); + else if(strncmp(tmpbuf, "dynamicwindows", 14) == 0) + dw = child; + + _fix_button_owner(child, dw); + } + WinEndEnumWindows(henum); + return; +} + +/* Free bitmap data associated with a window */ +void _free_bitmap(HWND handle) +{ + HBITMAP hbm = (HBITMAP)dw_window_get_data(handle, "_dw_bitmap"); + HPS hps = (HPS)dw_window_get_data(handle, "_dw_hps"); + HDC hdc = (HDC)dw_window_get_data(handle, "_dw_hdc"); + HPIXMAP pixmap = (HPIXMAP)dw_window_get_data(handle, "_dw_hpixmap"); + HPIXMAP disable = (HPIXMAP)dw_window_get_data(handle, "_dw_hpixmap_disabled"); + HPOINTER icon = (HPOINTER)dw_window_get_data(handle, "_dw_button_icon"); + + if(icon) + WinDestroyPointer(icon); + + if(pixmap) + dw_pixmap_destroy(pixmap); + + if(disable) + dw_pixmap_destroy(disable); + + if(hps) + { + GpiSetBitmap(hps, NULLHANDLE); + GpiAssociate(hps, NULLHANDLE); + GpiDestroyPS(hps); + } + + if(hdc) + DevCloseDC(hdc); + + if(hbm) + GpiDeleteBitmap(hbm); +} + +/* This function removes any handlers on windows and frees + * the user memory allocated to it. + */ +void _free_window_memory(HWND handle) +{ + HENUM henum; + HWND child; + void *ptr = (void *)WinQueryWindowPtr(handle, QWP_USER); + + dw_signal_disconnect_by_window(handle); + + if((child = WinWindowFromID(handle, FID_MENU)) != NULLHANDLE) + _free_menu_data(child); + + if((child = WinWindowFromID(handle, FID_CLIENT)) != NULLHANDLE) + { + Box *box = (Box *)WinQueryWindowPtr(child, QWP_USER); + + if(box && !dw_window_get_data(handle, "_dw_box")) + { + if(box->count && box->items) + free(box->items); + + WinSetWindowPtr(child, QWP_USER, 0); + free(box); + } + } + + if(ptr) + { + WindowData *wd = (WindowData *)ptr; + char tmpbuf[100]; + + WinQueryClassName(handle, 99, tmpbuf); + + if(strncmp(tmpbuf, "ColorSelectClass", 17)!=0) + { + /* If this window has an associate bitmap destroy it. */ + _free_bitmap(handle); + + if(strncmp(tmpbuf, "#1", 3)==0 && !WinWindowFromID(handle, FID_CLIENT)) + { + Box *box = (Box *)ptr; + + if(box->count && box->items) + free(box->items); + } + else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0) + { + void *data = dw_window_get_data(handle, "_dw_percent"); + + if(data) + free(data); + } + else if(strncmp(tmpbuf, "#37", 4)==0) + { + dw_container_clear(handle, FALSE); + if(wd && dw_window_get_data(handle, "_dw_container")) + { + void *oldflags = wd->data; + + wd->data = NULL; + free(oldflags); + } + } + + if(wd->oldproc) + WinSubclassWindow(handle, wd->oldproc); + + dw_window_set_data(handle, NULL, NULL); + WinSetWindowPtr(handle, QWP_USER, 0); + free(ptr); + } + } + + henum = WinBeginEnumWindows(handle); + while((child = WinGetNextWindow(henum)) != NULLHANDLE) + _free_window_memory(child); + + WinEndEnumWindows(henum); + return; +} + +void _free_menu_data(HWND menu) +{ + int i, count = (int)WinSendMsg(menu, MM_QUERYITEMCOUNT, 0, 0); + + dw_signal_disconnect_by_name(menu, DW_SIGNAL_CLICKED); + _free_window_memory(menu); + + for(i=0;i<count;i++) + { + SHORT menuid = (SHORT)WinSendMsg(menu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(i), 0); + MENUITEM mi; + + /* Free the data associated with the ID */ + if(menuid >= 30000) + { + char buffer[31] = {0}; + + sprintf(buffer, "_dw_id%ld", menuid); + dw_window_set_data( hwndApp, buffer, NULL ); + sprintf(buffer, "_dw_checkable%ld", menuid); + dw_window_set_data( hwndApp, buffer, NULL ); + sprintf(buffer, "_dw_ischecked%ld", menuid); + dw_window_set_data( hwndApp, buffer, NULL ); + sprintf(buffer, "_dw_isdisabled%ld", menuid); + dw_window_set_data( hwndApp, buffer, NULL ); + } + + /* Check any submenus */ + if(WinSendMsg(menu, MM_QUERYITEM, MPFROMSHORT(menuid), MPFROMP(&mi)) + && mi.hwndSubMenu) + _free_menu_data(mi.hwndSubMenu); + } +} + +/* This function returns 1 if the window (widget) handle + * passed to it is a valid window that can gain input focus. + */ +int _validate_focus(HWND handle) +{ + char tmpbuf[100]; + + if(!handle) + return 0; + + WinQueryClassName(handle, 99, tmpbuf); + + if(!WinIsWindowEnabled(handle) || + (strncmp(tmpbuf, "ColorSelectClass", 17) && dw_window_get_data(handle, "_dw_disabled"))) + return 0; + + /* These are the window classes which can + * obtain input focus. + */ + if(strncmp(tmpbuf, "#2", 3)==0 || /* Combobox */ + strncmp(tmpbuf, "#3", 3)==0 || /* Button */ + strncmp(tmpbuf, "#6", 3)==0 || /* Entryfield */ + strncmp(tmpbuf, "#7", 3)==0 || /* List box */ + strncmp(tmpbuf, "#10", 4)==0 || /* MLE */ + strncmp(tmpbuf, "#32", 4)==0 || /* Spinbutton */ + strncmp(tmpbuf, "#37", 4)==0 || /* Container */ + strncmp(tmpbuf, "#38", 4)== 0) /* Slider */ + return 1; + return 0; +} + +int _focus_check_box(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=box->count-1;z>-1;z--) + { + 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)) + 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] = ""; + + WinQueryClassName(box->items[z].hwnd, 99, tmpbuf); + 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"); + + if(mybox) + { + Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER); + + if(splitbox && _focus_check_box(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(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(scrollbox, handle, start == 3 ? 3 : 0, 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)) + 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] = ""; + + WinQueryClassName(box->items[z].hwnd, 99, 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; +} + +/* This function finds the first widget in the + * layout and moves the current focus to it. + */ +int _initial_focus(HWND handle) +{ + Box *thisbox = NULL; + HWND box; + + box = WinWindowFromID(handle, FID_CLIENT); + if(box) + thisbox = WinQueryWindowPtr(box, QWP_USER); + else + return 1; + + if(thisbox) + _focus_check_box(thisbox, handle, 3, 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) +{ + 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(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); + } +} + +/* This function will recursively search a box and add up the total height of it */ +void _count_size(HWND box, int type, int *xsize, int *xorigsize) +{ + int size = 0, origsize = 0, z; + Box *tmp = WinQueryWindowPtr(box, QWP_USER); + + if(!tmp) + { + *xsize = *xorigsize = 0; + return; + } + + if(type == tmp->type) + { + /* If the box is going in the direction we want, then we + * return the entire sum of the items. + */ + for(z=0;z<tmp->count;z++) + { + if(tmp->items[z].type == TYPEBOX) + { + int s, os; + + _count_size(tmp->items[z].hwnd, type, &s, &os); + size += s; + origsize += os; + } + else + { + size += (type == DW_HORZ ? tmp->items[z].width : tmp->items[z].height); + origsize += (type == DW_HORZ ? tmp->items[z].origwidth : tmp->items[z].origheight); + } + } + } + else + { + /* If the box is not going in the direction we want, then we only + * want to return the maximum value. + */ + int tmpsize = 0, tmporigsize = 0; + + for(z=0;z<tmp->count;z++) + { + if(tmp->items[z].type == TYPEBOX) + _count_size(tmp->items[z].hwnd, type, &tmpsize, &tmporigsize); + else + { + tmpsize = (type == DW_HORZ ? tmp->items[z].width : tmp->items[z].height); + tmporigsize = (type == DW_HORZ ? tmp->items[z].origwidth : tmp->items[z].origheight); + } + + if(tmpsize > size) + size = tmpsize; + } + } + + *xsize = size; + *xorigsize = origsize; +} + + +/* Function: TrackRectangle + * Abstract: Tracks given rectangle. + * + * If rclBounds is NULL, then track rectangle on entire desktop. + * rclTrack is in window coorditates and will be mapped to + * desktop. + */ + +BOOL _TrackRectangle(HWND hwndBase, RECTL* rclTrack, RECTL* rclBounds) +{ + TRACKINFO track; + APIRET rc; + + track.cxBorder = 1; + track.cyBorder = 1; + track.cxGrid = 1; + track.cyGrid = 1; + track.cxKeyboard = 8; + track.cyKeyboard = 8; + + if(!rclTrack) + return FALSE; + + if(rclBounds) + { + track.rclBoundary = *rclBounds; + } + else + { + track.rclBoundary.yTop = + track.rclBoundary.xRight = 3000; + track.rclBoundary.yBottom = + track.rclBoundary.xLeft = -3000; + } + + track.rclTrack = *rclTrack; + + WinMapWindowPoints(hwndBase, + HWND_DESKTOP, + (PPOINTL)&track.rclTrack, + 2); + + track.ptlMinTrackSize.x = track.rclTrack.xRight + - track.rclTrack.xLeft; + track.ptlMinTrackSize.y = track.rclTrack.yTop + - track.rclTrack.yBottom; + track.ptlMaxTrackSize.x = track.rclTrack.xRight + - track.rclTrack.xLeft; + track.ptlMaxTrackSize.y = track.rclTrack.yTop + - track.rclTrack.yBottom; + + track.fs = TF_MOVE | TF_ALLINBOUNDARY; + + rc = WinTrackRect(HWND_DESKTOP, 0, &track); + + if(rc) + *rclTrack = track.rclTrack; + + return rc; +} + +void _check_resize_notebook(HWND hwnd) +{ + char tmpbuf[100]; + + WinQueryClassName(hwnd, 99, tmpbuf); + + /* If we have a notebook we resize the page again. */ + if(strncmp(tmpbuf, "#40", 4)==0) + { + long x, y; + unsigned long width, height; + ULONG page = (ULONG)WinSendMsg(hwnd, BKM_QUERYPAGEID, 0, MPFROM2SHORT(BKA_FIRST, BKA_MAJOR)); + + while(page) + { + HWND pagehwnd = (HWND)WinSendMsg(hwnd, BKM_QUERYPAGEWINDOWHWND, MPFROMLONG(page), 0); + RECTL rc; + + Box *pagebox = (Box *)WinQueryWindowPtr(pagehwnd, QWP_USER); + if(pagebox) + { + dw_window_get_pos_size(hwnd, &x, &y, &width, &height); + + rc.xLeft = x; + rc.yBottom = y; + rc.xRight = x + width; + rc.yTop = y + height; + + WinSendMsg(hwnd, BKM_CALCPAGERECT, (MPARAM)&rc, (MPARAM)TRUE); + + _do_resize(pagebox, rc.xRight - rc.xLeft, rc.yTop - rc.yBottom); + } + page = (ULONG)WinSendMsg(hwnd, BKM_QUERYPAGEID, (MPARAM)page, MPFROM2SHORT(BKA_NEXT, BKA_MAJOR)); + } + + } +} + +/* Return the OS/2 color from the DW color */ +unsigned long _internal_color(unsigned long color) +{ + if(color < 16) + return _colors[color]; + return color; +} + +unsigned long _os2_color(unsigned long color) +{ + return DW_RED_VALUE(color) << 16 | DW_GREEN_VALUE(color) << 8 | DW_BLUE_VALUE(color); +} + +BOOL _MySetWindowPos(HWND hwnd, HWND parent, HWND behind, LONG x, LONG y, LONG cx, LONG cy, ULONG fl) +{ + int height = _get_height(parent); + + return WinSetWindowPos(hwnd, behind, x, height - y - cy, cx, cy, fl); +} + +#define _DW_DEFAULT_SCROLLBAR_WIDTH 16 + +/* This function calculates how much space the widgets and boxes require + * and does expansion as necessary. + */ +int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy, + int pass, int *usedpadx, int *usedpady) +{ + int z, currentx = 0, currenty = 0; + int uymax = 0, uxmax = 0; + int upymax = 0, upxmax = 0; + /* Used for the SIZEEXPAND */ + int nux = *usedx, nuy = *usedy; + int nupx = *usedpadx, nupy = *usedpady; + + (*usedx) += (thisbox->pad * 2); + (*usedy) += (thisbox->pad * 2); + + if(thisbox->grouphwnd) + { + char *text = dw_window_get_text(thisbox->grouphwnd); + + thisbox->grouppady = 0; + + if(text) + { + dw_font_text_extents_get(thisbox->grouphwnd, 0, text, NULL, &thisbox->grouppady); + dw_free(text); + } + + if(thisbox->grouppady) + thisbox->grouppady += 3; + else + thisbox->grouppady = 6; + + thisbox->grouppadx = 6; + + (*usedx) += thisbox->grouppadx; + (*usedpadx) += thisbox->grouppadx; + (*usedy) += thisbox->grouppady; + (*usedpady) += thisbox->grouppady; + } + + for(z=0;z<thisbox->count;z++) + { + if(thisbox->items[z].type == TYPEBOX) + { + int initialx, initialy; + Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER); + + initialx = x - (*usedx); + initialy = y - (*usedy); + + if(tmp) + { + int newx, newy; + int nux = *usedx, nuy = *usedy; + int upx = *usedpadx + (tmp->pad*2), upy = *usedpady + (tmp->pad*2); + + /* On the second pass we know how big the box needs to be and how + * much space we have, so we can calculate a ratio for the new box. + */ + if(pass == 2) + { + int deep = *depth + 1; + + _resize_box(tmp, &deep, x, y, &nux, &nuy, 1, &upx, &upy); + + tmp->upx = upx - *usedpadx; + tmp->upy = upy - *usedpady; + + newx = x - nux; + newy = y - nuy; + + tmp->width = thisbox->items[z].width = initialx - newx; + tmp->height = thisbox->items[z].height = initialy - newy; + + tmp->parentxratio = thisbox->xratio; + tmp->parentyratio = thisbox->yratio; + + tmp->parentpad = tmp->pad; + + /* Just in case */ + tmp->xratio = thisbox->xratio; + tmp->yratio = thisbox->yratio; + + if(thisbox->type == DW_VERT) + { + int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppady; + + if((thisbox->items[z].width - tmppad)!=0) + tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmppad))/((float)(thisbox->items[z].width-tmppad)); + } + else + { + if((thisbox->items[z].width-tmp->upx)!=0) + tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx)); + } + if(thisbox->type == DW_HORZ) + { + int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppadx; + + if((thisbox->items[z].height-tmppad)!=0) + tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmppad))/((float)(thisbox->items[z].height-tmppad)); + } + else + { + if((thisbox->items[z].height-tmp->upy)!=0) + tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy)); + } + + nux = *usedx; nuy = *usedy; + upx = *usedpadx + (tmp->pad*2); upy = *usedpady + (tmp->pad*2); + } + + (*depth)++; + + _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy); + + (*depth)--; + + newx = x - nux; + newy = y - nuy; + + tmp->minwidth = thisbox->items[z].width = initialx - newx; + tmp->minheight = thisbox->items[z].height = initialy - newy; + } + } + + if(pass > 1 && *depth > 0) + { + if(thisbox->type == DW_VERT) + { + int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppadx; + + if((thisbox->minwidth-tmppad) == 0) + thisbox->items[z].xratio = 1.0; + else + thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-tmppad))/((float)(thisbox->minwidth-tmppad)); + } + else + { + if(thisbox->minwidth-thisbox->upx == 0) + thisbox->items[z].xratio = 1.0; + else + thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx)); + } + + if(thisbox->type == DW_HORZ) + { + int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppady; + + if((thisbox->minheight-tmppad) == 0) + thisbox->items[z].yratio = 1.0; + else + thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-tmppad))/((float)(thisbox->minheight-tmppad)); + } + else + { + if(thisbox->minheight-thisbox->upy == 0) + thisbox->items[z].yratio = 1.0; + else + thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy)); + } + + if(thisbox->items[z].type == TYPEBOX) + { + Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER); + + if(tmp) + { + tmp->parentxratio = thisbox->items[z].xratio; + tmp->parentyratio = thisbox->items[z].yratio; + } + } + } + else + { + thisbox->items[z].xratio = thisbox->xratio; + thisbox->items[z].yratio = thisbox->yratio; + } + + if(thisbox->type == DW_VERT) + { + int itemwidth = thisbox->items[z].width + (thisbox->items[z].pad*2); + + if(itemwidth > uxmax) + uxmax = itemwidth; + if(thisbox->items[z].hsize != SIZEEXPAND) + { + if(itemwidth > upxmax) + upxmax = itemwidth; + } + else + { + if(thisbox->items[z].pad*2 > upxmax) + upxmax = thisbox->items[z].pad*2; + } + } + else + { + if(thisbox->items[z].width == -1) + { + /* figure out how much space this item requires */ + /* thisbox->items[z].width = */ + } + else + { + (*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2); + if(thisbox->items[z].hsize != SIZEEXPAND) + (*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width; + else + (*usedpadx) += thisbox->items[z].pad*2; + } + } + if(thisbox->type == DW_HORZ) + { + int itemheight = thisbox->items[z].height + (thisbox->items[z].pad*2); + + if(itemheight > uymax) + uymax = itemheight; + if(thisbox->items[z].vsize != SIZEEXPAND) + { + if(itemheight > upymax) + upymax = itemheight; + } + else + { + if(thisbox->items[z].pad*2 > upymax) + upymax = thisbox->items[z].pad*2; + } + } + else + { + if(thisbox->items[z].height == -1) + { + /* figure out how much space this item requires */ + /* thisbox->items[z].height = */ + } + else + { + (*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2); + if(thisbox->items[z].vsize != SIZEEXPAND) + (*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height; + else + (*usedpady) += thisbox->items[z].pad*2; + } + } + } + + (*usedx) += uxmax; + (*usedy) += uymax; + (*usedpadx) += upxmax; + (*usedpady) += upymax; + + currentx += thisbox->pad; + currenty += thisbox->pad; + + if(thisbox->grouphwnd) + { + currentx += 3; + currenty += thisbox->grouppady - 3; + } + + /* The second pass is for expansion and actual placement. */ + if(pass > 1) + { + /* Any SIZEEXPAND items should be set to uxmax/uymax */ + for(z=0;z<thisbox->count;z++) + { + if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == DW_VERT) + thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2); + if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == DW_HORZ) + thisbox->items[z].height = uymax-(thisbox->items[z].pad*2); + /* Run this code segment again to finalize the sized after setting uxmax/uymax values. */ + if(thisbox->items[z].type == TYPEBOX) + { + Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER); + + if(tmp) + { + if(*depth > 0) + { + float calcval; + + if(thisbox->type == DW_VERT) + { + calcval = (float)(tmp->minwidth-((thisbox->items[z].pad*2)+(thisbox->pad*2))); + if(calcval == 0.0) + tmp->xratio = thisbox->xratio; + else + tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval; + tmp->width = thisbox->items[z].width; + } + if(thisbox->type == DW_HORZ) + { + calcval = (float)(tmp->minheight-((thisbox->items[z].pad*2)+(thisbox->pad*2))); + if(calcval == 0.0) + tmp->yratio = thisbox->yratio; + else + tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval; + tmp->height = thisbox->items[z].height; + } + } + + (*depth)++; + + _resize_box(tmp, depth, x, y, &nux, &nuy, 3, &nupx, &nupy); + + (*depth)--; + + } + } + } + + for(z=0;z<(thisbox->count);z++) + { + int height = thisbox->items[z].height; + int width = thisbox->items[z].width; + int pad = thisbox->items[z].pad; + HWND handle = thisbox->items[z].hwnd; + int vectorx, vectory; + + /* When upxmax != pad*2 then ratios are incorrect. */ + vectorx = (int)((width*thisbox->items[z].xratio)-width); + vectory = (int)((height*thisbox->items[z].yratio)-height); + + if(width > 0 && height > 0) + { + char tmpbuf[100]; + /* This is a hack to fix rounding of the sizing */ + if(*depth == 0) + { + vectorx++; + vectory++; + } + + /* If this item isn't going to expand... reset the vectors to 0 */ + if(thisbox->items[z].vsize != SIZEEXPAND) + vectory = 0; + if(thisbox->items[z].hsize != SIZEEXPAND) + vectorx = 0; + + WinQueryClassName(handle, 99, tmpbuf); + + if(strncmp(tmpbuf, "#2", 3)==0) + { + HWND frame = (HWND)dw_window_get_data(handle, "_dw_combo_box"); + /* Make the combobox big enough to drop down. :) */ + WinSetWindowPos(handle, HWND_TOP, 0, -100, + width + vectorx, (height + vectory) + 100, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + _MySetWindowPos(frame, thisbox->hwnd, HWND_TOP, currentx + pad, currenty + pad, + width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + } + else if(strncmp(tmpbuf, "#6", 3)==0) + { + /* Entryfields on OS/2 have a thick border that isn't on Windows and GTK */ + _MySetWindowPos(handle, thisbox->hwnd, HWND_TOP, (currentx + pad) + 3, (currenty + pad) + 3, + (width + vectorx) - 6, (height + vectory) - 6, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + } + else if(strncmp(tmpbuf, "#40", 5)==0) + { + _MySetWindowPos(handle, thisbox->hwnd, HWND_TOP, currentx + pad, currenty + pad, + width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + _check_resize_notebook(handle); + } + else if(strncmp(tmpbuf, ScrollClassName, strlen(ScrollClassName)+1)==0) + { + /* Handle special case of scrollbox */ + int cx = width + vectorx; + int cy = height + vectory; + int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0; + HWND box = (HWND)dw_window_get_data(handle, "_dw_resizebox"); + HWND client = WinWindowFromID(handle, FID_CLIENT); + HWND vscroll = WinWindowFromID(handle, FID_VERTSCROLL); + HWND hscroll = WinWindowFromID(handle, FID_HORZSCROLL); + Box *contentbox = (Box *)WinQueryWindowPtr(box, QWP_USER); + int origx, origy; + unsigned int hpos = (unsigned int)WinSendMsg(hscroll, SBM_QUERYPOS, 0, 0); + unsigned int vpos = (unsigned int)WinSendMsg(vscroll, SBM_QUERYPOS, 0, 0); + + /* Position the scrollbox parts */ + _MySetWindowPos(handle, thisbox->hwnd, HWND_TOP, currentx + pad, currenty + pad, cx, cy, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + WinSetWindowPos(client, HWND_TOP, 0, _DW_DEFAULT_SCROLLBAR_WIDTH, cx - _DW_DEFAULT_SCROLLBAR_WIDTH, cy - _DW_DEFAULT_SCROLLBAR_WIDTH, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + WinSetWindowPos(hscroll, HWND_TOP, 0, 0, cx - _DW_DEFAULT_SCROLLBAR_WIDTH, _DW_DEFAULT_SCROLLBAR_WIDTH, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + WinSetWindowPos(vscroll, HWND_TOP, cx - _DW_DEFAULT_SCROLLBAR_WIDTH, _DW_DEFAULT_SCROLLBAR_WIDTH, _DW_DEFAULT_SCROLLBAR_WIDTH, cy - _DW_DEFAULT_SCROLLBAR_WIDTH, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + + origx = cx = cx - _DW_DEFAULT_SCROLLBAR_WIDTH; + origy = cy = cy - _DW_DEFAULT_SCROLLBAR_WIDTH; + + /* Get the required space for the box */ + _resize_box(contentbox, &depth, cx, cy, &usedx, &usedy, 1, &usedpadx, &usedpady); + + if(cx < usedx) + { + cx = usedx; + } + if(cy < usedy) + { + cy = usedy; + } + + /* Setup vertical scroller */ + WinSendMsg(vscroll, SBM_SETSCROLLBAR, (MPARAM)vpos, MPFROM2SHORT(0, (unsigned short)usedy - origy)); + WinSendMsg(vscroll, SBM_SETTHUMBSIZE, MPFROM2SHORT((unsigned short)origy, usedy), 0); + if(vpos > usedy) + { + vpos = usedy; + WinSendMsg(vscroll, SBM_SETPOS, (MPARAM)vpos, 0); + } + + /* Setup horizontal scroller */ + WinSendMsg(hscroll, SBM_SETSCROLLBAR, (MPARAM)hpos, MPFROM2SHORT(0, (unsigned short)usedx - origx)); + WinSendMsg(hscroll, SBM_SETTHUMBSIZE, MPFROM2SHORT((unsigned short)origx, usedx), 0); + if(hpos > usedx) + { + hpos = usedx; + WinSendMsg(hscroll, SBM_SETPOS, (MPARAM)hpos, 0); + } + + /* Position the scrolled box */ + WinSetWindowPos(box, HWND_TOP, 0, -(cy - origy), cx, cy, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + + dw_window_set_data(handle, "_dw_cy", (void *)(cy - origy)); + + /* Layout the content of the scrollbox */ + _do_resize(contentbox, cx, cy); + } + else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0) + { + /* 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 cx = width + vectorx; + int cy = height + vectory; + + _MySetWindowPos(handle, thisbox->hwnd, HWND_TOP, currentx + pad, currenty + pad, + cx, cy, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + + if(cx > 0 && cy > 0 && percent) + _handle_splitbar_resize(handle, *percent, type, cx, cy); + } + else + { + _MySetWindowPos(handle, thisbox->hwnd, HWND_TOP, currentx + pad, currenty + pad, + width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER); + if(thisbox->items[z].type == TYPEBOX) + { + Box *boxinfo = WinQueryWindowPtr(handle, QWP_USER); + + if(boxinfo && boxinfo->grouphwnd) + WinSetWindowPos(boxinfo->grouphwnd, HWND_TOP, 0, 0, + width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE); + + } + + } + + if(thisbox->type == DW_HORZ) + currentx += width + vectorx + (pad * 2); + if(thisbox->type == DW_VERT) + currenty += height + vectory + (pad * 2); + } + } + } + return 0; +} + +void _do_resize(Box *thisbox, int x, int y) +{ + if(x != 0 && y != 0) + { + if(thisbox) + { + int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0; + + _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady); + + if(usedx-usedpadx == 0 || usedy-usedpady == 0) + return; + + thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx)); + thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady)); + + usedx = usedy = usedpadx = usedpady = depth = 0; + + _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady); + } + } +} + +/* This procedure handles WM_QUERYTRACKINFO requests from the frame */ +MRESULT EXPENTRY _sizeproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER); + Box *thisbox = NULL; + HWND box; + + box = WinWindowFromID(hWnd, FID_CLIENT); + if(box) + thisbox = WinQueryWindowPtr(box, QWP_USER); + + if(thisbox && !thisbox->titlebar) + { + switch(msg) + { + case WM_QUERYTRACKINFO: + { + if(blah && *blah) + { + PTRACKINFO ptInfo; + int res; + PFNWP myfunc = *blah; + res = (int)myfunc(hWnd, msg, mp1, mp2); + + ptInfo = (PTRACKINFO)(mp2); + + ptInfo->ptlMinTrackSize.y = 8; + ptInfo->ptlMinTrackSize.x = 8; + + return (MRESULT)res; + } + } + } + } + + if(blah && *blah) + { + PFNWP myfunc = *blah; + return myfunc(hWnd, msg, mp1, mp2); + } + + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +void _Top(HPS hpsPaint, RECTL rclPaint) +{ + POINTL ptl1, ptl2; + + ptl1.x = rclPaint.xLeft; + ptl2.y = ptl1.y = rclPaint.yTop - 1; + ptl2.x = rclPaint.xRight - 1; + GpiMove(hpsPaint, &ptl1); + GpiLine(hpsPaint, &ptl2); +} + +/* Left hits the bottom */ +void _Left(HPS hpsPaint, RECTL rclPaint) +{ + POINTL ptl1, ptl2; + + ptl2.x = ptl1.x = rclPaint.xLeft; + ptl1.y = rclPaint.yTop - 1; + ptl2.y = rclPaint.yBottom; + GpiMove(hpsPaint, &ptl1); + GpiLine(hpsPaint, &ptl2); +} + +void _Bottom(HPS hpsPaint, RECTL rclPaint) +{ + POINTL ptl1, ptl2; + + ptl1.x = rclPaint.xRight - 1; + ptl1.y = ptl2.y = rclPaint.yBottom; + ptl2.x = rclPaint.xLeft; + GpiMove(hpsPaint, &ptl1); + GpiLine(hpsPaint, &ptl2); +} + +/* Right hits the top */ +void _Right(HPS hpsPaint, RECTL rclPaint) +{ + POINTL ptl1, ptl2; + + ptl2.x = ptl1.x = rclPaint.xRight - 1; + ptl1.y = rclPaint.yBottom + 1; + ptl2.y = rclPaint.yTop - 1; + GpiMove(hpsPaint, &ptl1); + GpiLine(hpsPaint, &ptl2); +} + +/* This procedure handles drawing of a status border */ +MRESULT EXPENTRY _statusproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER); + + if(msg == WM_MOUSEMOVE && _wndproc(hWnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + + if(blah && *blah) + { + PFNWP myfunc = *blah; + + switch(msg) + { + case WM_PAINT: + { + HPS hpsPaint; + RECTL rclPaint; + char buf[1024]; + + hpsPaint = WinBeginPaint(hWnd, 0, 0); + WinQueryWindowRect(hWnd, &rclPaint); + WinFillRect(hpsPaint, &rclPaint, CLR_PALEGRAY); + + GpiSetColor(hpsPaint, CLR_DARKGRAY); + _Top(hpsPaint, rclPaint); + _Left(hpsPaint, rclPaint); + + GpiSetColor(hpsPaint, CLR_WHITE); + _Right(hpsPaint, rclPaint); + _Bottom(hpsPaint, rclPaint); + + WinQueryWindowText(hWnd, 1024, buf); + rclPaint.xLeft += 3; + rclPaint.xRight--; + rclPaint.yTop--; + rclPaint.yBottom++; + + GpiSetColor(hpsPaint, CLR_BLACK); + WinDrawText(hpsPaint, -1, buf, &rclPaint, DT_TEXTATTRS, DT_TEXTATTRS, DT_VCENTER | DT_LEFT | DT_TEXTATTRS); + WinEndPaint(hpsPaint); + + return (MRESULT)TRUE; + } + } + return myfunc(hWnd, msg, mp1, mp2); + } + + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +/* This procedure handles pointer changes */ +MRESULT EXPENTRY _textproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER); + + if(msg == WM_MOUSEMOVE &&_wndproc(hWnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + + if(blah && *blah) + { + PFNWP myfunc = *blah; + + return myfunc(hWnd, msg, mp1, mp2); + } + + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +/* This procedure handles scrollbox */ +MRESULT EXPENTRY _scrollwndproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + switch(msg) + { + case WM_PAINT: + { + HPS hpsPaint; + RECTL rclPaint; + + hpsPaint = WinBeginPaint(hWnd, 0, 0); + WinQueryWindowRect(hWnd, &rclPaint); + WinFillRect(hpsPaint, &rclPaint, CLR_PALEGRAY); + WinEndPaint(hpsPaint); + + break; + } + case WM_HSCROLL: + case WM_VSCROLL: + { + MPARAM res; + int *pos, min, max, page, which = SHORT2FROMMP(mp2); + HWND handle, client = WinWindowFromID(hWnd, FID_CLIENT); + HWND box = (HWND)dw_window_get_data(hWnd, "_dw_resizebox"); + HWND hscroll = WinWindowFromID(hWnd, FID_HORZSCROLL); + HWND vscroll = WinWindowFromID(hWnd, FID_VERTSCROLL); + int hpos = dw_scrollbar_get_pos(hscroll); + int vpos = dw_scrollbar_get_pos(vscroll); + int cy = (int)dw_window_get_data(hWnd, "_dw_cy"); + RECTL rect; + + WinQueryWindowRect(client, &rect); + + if(msg == WM_VSCROLL) + { + page = rect.yTop - rect.yBottom; + handle = vscroll; + pos = &vpos; + } + else + { + page = rect.xRight - rect.xLeft; + handle = hscroll; + pos = &hpos; + } + + res = WinSendMsg(handle, SBM_QUERYRANGE, 0, 0); + min = SHORT1FROMMP(res); + max = SHORT2FROMMP(res); + + switch(which) + { + case SB_SLIDERTRACK: + *pos = SHORT1FROMMP(mp2); + break; + case SB_LINEUP: + (*pos)--; + if(*pos < min) + *pos = min; + break; + case SB_LINEDOWN: + (*pos)++; + if(*pos > max) + *pos = max; + break; + case SB_PAGEUP: + (*pos) -= page; + if(*pos < min) + *pos = min; + break; + case SB_PAGEDOWN: + (*pos) += page; + if(*pos > max) + *pos = max; + break; + } + WinSendMsg(handle, SBM_SETPOS, (MPARAM)*pos, 0); + /* Position the scrolled box */ + WinSetWindowPos(box, HWND_TOP, -hpos, -(cy - vpos), 0, 0, SWP_MOVE); + break; + } + } + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +void _click_default(HWND handle) +{ + char tmpbuf[100]; + + WinQueryClassName(handle, 99, tmpbuf); + + /* These are the window classes which can + * obtain input focus. + */ + if(strncmp(tmpbuf, "#3", 3)==0) + { + /* Generate click on default item */ + SignalHandler *tmp = Root; + + /* Find any callbacks for this function */ + while(tmp) + { + if(tmp->message == WM_COMMAND) + { + int (* API clickfunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction; + + /* Make sure it's the right window, and the right ID */ + if(tmp->window == handle) + { + clickfunc(tmp->window, tmp->data); + tmp = NULL; + } + } + if(tmp) + tmp= tmp->next; + } + } + else + WinSetFocus(HWND_DESKTOP, handle); +} + +#define ENTRY_CUT 60901 +#define ENTRY_COPY 60902 +#define ENTRY_PASTE 60903 +#define ENTRY_UNDO 60904 +#define ENTRY_SALL 60905 + +/* Originally just intended for entryfields, it now serves as a generic + * procedure for handling TAB presses to change input focus on controls. + */ +MRESULT EXPENTRY _entryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER); + PFNWP oldproc = 0; + char tmpbuf[100]; + + if(blah) + oldproc = blah->oldproc; + + WinQueryClassName(hWnd, 99, tmpbuf); + + /* These are the window classes which should get a menu */ + if(strncmp(tmpbuf, "#2", 3)==0 || /* Combobox */ + strncmp(tmpbuf, "#6", 3)==0 || /* Entryfield */ + strncmp(tmpbuf, "#10", 4)==0 || /* MLE */ + strncmp(tmpbuf, "#32", 4)==0) /* Spinbutton */ + { + switch(msg) + { + case WM_CONTEXTMENU: + { + HMENUI hwndMenu = dw_menu_new(0L); + long x, y; + + if(strncmp(tmpbuf, "#10", 4)==0 && !WinSendMsg(hWnd, MLM_QUERYREADONLY, 0, 0)) + { + dw_menu_append_item(hwndMenu, "Undo", ENTRY_UNDO, 0L, TRUE, -1, 0L); + dw_menu_append_item(hwndMenu, "", 0L, 0L, TRUE, -1, 0L); + } + dw_menu_append_item(hwndMenu, "Copy", ENTRY_COPY, 0L, TRUE, -1, 0L); + if((strncmp(tmpbuf, "#10", 4)!=0 && !dw_window_get_data(hWnd, "_dw_disabled")) || (strncmp(tmpbuf, "#10", 4)==0 && !WinSendMsg(hWnd, MLM_QUERYREADONLY, 0, 0))) + { + dw_menu_append_item(hwndMenu, "Cut", ENTRY_CUT, 0L, TRUE, -1, 0L); + dw_menu_append_item(hwndMenu, "Paste", ENTRY_PASTE, 0L, TRUE, -1, 0L); + } + dw_menu_append_item(hwndMenu, "", 0L, 0L, TRUE, -1, 0L); + dw_menu_append_item(hwndMenu, "Select All", ENTRY_SALL, 0L, TRUE, -1, 0L); + + WinSetFocus(HWND_DESKTOP, hWnd); + dw_pointer_query_pos(&x, &y); + dw_menu_popup(&hwndMenu, hWnd, x, y); + } + break; + case WM_COMMAND: + { + ULONG command = COMMANDMSG(&msg)->cmd; + + /* MLE */ + if(strncmp(tmpbuf, "#10", 4)==0) + { + switch(command) + { + case ENTRY_CUT: + return WinSendMsg(hWnd, MLM_CUT, 0, 0); + case ENTRY_COPY: + return WinSendMsg(hWnd, MLM_COPY, 0, 0); + case ENTRY_PASTE: + return WinSendMsg(hWnd, MLM_PASTE, 0, 0); + case ENTRY_UNDO: + return WinSendMsg(hWnd, MLM_UNDO, 0, 0); + case ENTRY_SALL: + { + ULONG len = (ULONG)WinSendMsg(hWnd, MLM_QUERYTEXTLENGTH, 0, 0); + return WinSendMsg(hWnd, MLM_SETSEL, 0, (MPARAM)len); + } + } + } + else /* Other */ + { + HWND handle = hWnd; + + /* Get the entryfield handle from multi window controls */ + if(strncmp(tmpbuf, "#2", 3)==0) + handle = WinWindowFromID(hWnd, 667); + + if(handle) + { + switch(command) + { + case ENTRY_CUT: + return WinSendMsg(handle, EM_CUT, 0, 0); + case ENTRY_COPY: + return WinSendMsg(handle, EM_COPY, 0, 0); + case ENTRY_PASTE: + return WinSendMsg(handle, EM_PASTE, 0, 0); + case ENTRY_SALL: + { + LONG len = WinQueryWindowTextLength(hWnd); + return WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT(0, (SHORT)len), 0); + } + } + } + } + } + break; + } + } + + switch(msg) + { + case WM_BUTTON1DOWN: + case WM_BUTTON2DOWN: + case WM_BUTTON3DOWN: + { + if(strncmp(tmpbuf, "#32", 4)==0) + _run_event(hWnd, WM_SETFOCUS, (MPARAM)FALSE, (MPARAM)TRUE); + } + break; + case WM_CONTROL: + { + if(strncmp(tmpbuf, "#38", 4)==0) + _run_event(hWnd, msg, mp1, mp2); + } + break; + case WM_SETFOCUS: + _run_event(hWnd, msg, mp1, mp2); + break; + case WM_CHAR: + if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE) + return (MRESULT)TRUE; + if(SHORT1FROMMP(mp2) == '\t') + { + if(CHARMSG(&msg)->fs & KC_SHIFT) + _shift_focus_back(hWnd); + else + _shift_focus(hWnd); + return FALSE; + } + else if(SHORT1FROMMP(mp2) == '\r' && blah && blah->clickdefault) + _click_default(blah->clickdefault); + /* When you hit escape we get this value and the + * window hangs for reasons unknown. (in an MLE) + */ + else if(SHORT1FROMMP(mp2) == 283) + return (MRESULT)TRUE; + + break; + case WM_SIZE: + { + /* If it's a slider... make sure it shows the correct value */ + if(strncmp(tmpbuf, "#38", 4)==0) + WinPostMsg(hWnd, WM_USER+7, 0, 0); + } + break; + case WM_USER+7: + { + int pos = (int)dw_window_get_data(hWnd, "_dw_slider_value"); + WinSendMsg(hWnd, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), (MPARAM)pos); + } + break; + case WM_MOUSEMOVE: + if(_wndproc(hWnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + break; + } + + if(oldproc) + return oldproc(hWnd, msg, mp1, mp2); + + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +/* Deal with combobox specifics and enhancements */ +MRESULT EXPENTRY _comboentryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER); + + switch(msg) + { + case WM_MOUSEMOVE: + if(_wndproc(hWnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + break; + case WM_CONTEXTMENU: + case WM_COMMAND: + return _entryproc(hWnd, msg, mp1, mp2); + case WM_SETFOCUS: + _run_event(hWnd, msg, mp1, mp2); + break; + case WM_CHAR: + if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE) + return (MRESULT)TRUE; + /* A Similar problem to the MLE, if ESC just return */ + if(SHORT1FROMMP(mp2) == 283) + return (MRESULT)TRUE; + break; + } + + if(blah && blah->oldproc) + return blah->oldproc(hWnd, msg, mp1, mp2); + + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +/* Enhance the standard OS/2 MLE control */ +MRESULT EXPENTRY _mleproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + switch(msg) + { + case WM_VSCROLL: + if(SHORT2FROMMP(mp2) == SB_SLIDERTRACK) + { + USHORT pos = SHORT1FROMMP(mp2); + + WinSendMsg(hWnd, msg, mp1, MPFROM2SHORT(pos, SB_SLIDERPOSITION)); + } + break; + } + return _entryproc(hWnd, msg, mp1, mp2); +} + +/* Handle special messages for the spinbutton's entryfield */ +MRESULT EXPENTRY _spinentryproc(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_MOUSEMOVE: + if(_wndproc(hWnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + break; + case WM_CONTEXTMENU: + case WM_COMMAND: + return _entryproc(hWnd, msg, mp1, mp2); + } + + if(oldproc) + return oldproc(hWnd, msg, mp1, mp2); + + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +int _dw_int_pos(HWND hwnd) +{ + int pos = (int)dw_window_get_data(hwnd, "_dw_percent_value"); + int range = _dw_percent_get_range(hwnd); + float fpos = (float)pos; + float frange = (float)range; + float fnew = (fpos/1000.0)*frange; + return (int)fnew; +} + +void _dw_int_set(HWND hwnd, int pos) +{ + int inew, range = _dw_percent_get_range(hwnd); + if(range) + { + float fpos = (float)pos; + float frange = (float)range; + float fnew = (fpos/frange)*1000.0; + inew = (int)fnew; + dw_window_set_data(hwnd, "_dw_percent_value", (void *)inew); + } +} + +/* Handle size changes in the percent class */ +MRESULT EXPENTRY _percentproc(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_MOUSEMOVE: + if(_wndproc(hWnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + break; + case WM_SIZE: + WinPostMsg(hWnd, WM_USER+7, 0, 0); + break; + case WM_USER+7: + WinSendMsg(hWnd, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), (MPARAM)_dw_int_pos(hWnd)); + break; + } + + if(oldproc) + return oldproc(hWnd, msg, mp1, mp2); + + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +/* Handle correct painting of a combobox with the WS_CLIPCHILDREN + * flag enabled, and also handle TABs to switch input focus. + */ +MRESULT EXPENTRY _comboproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + WindowData *blah = WinQueryWindowPtr(hWnd, QWP_USER); + PFNWP oldproc = 0; + + if(blah) + oldproc = blah->oldproc; + + switch(msg) + { + case WM_MOUSEMOVE: + if(_wndproc(hWnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + break; + case WM_CHAR: + if(SHORT1FROMMP(mp2) == '\t') + { + if(CHARMSG(&msg)->fs & KC_SHIFT) + _shift_focus_back(hWnd); + else + _shift_focus(hWnd); + return FALSE; + } + else if(SHORT1FROMMP(mp2) == '\r' && blah && blah->clickdefault) + _click_default(blah->clickdefault); + break; + case WM_BUTTON1DBLCLK: + case WM_BUTTON2DBLCLK: + case WM_BUTTON3DBLCLK: + if(dw_window_get_data(hWnd, "_dw_disabled")) + return (MRESULT)TRUE; + break; + case WM_BUTTON1DOWN: + case WM_BUTTON2DOWN: + case WM_BUTTON3DOWN: + if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE) + return (MRESULT)TRUE; + _run_event(hWnd, WM_SETFOCUS, (MPARAM)FALSE, (MPARAM)TRUE); + break; + case WM_SETFOCUS: + _run_event(hWnd, msg, mp1, mp2); + break; + case WM_PAINT: + { + HWND entry, frame = (HWND)dw_window_get_data(hWnd, "_dw_combo_box"), parent = WinQueryWindow(frame, QW_PARENT); + HPS hpsPaint; + POINTL ptl; + unsigned long width, height, thumbheight = 0; + ULONG color; + + if((entry = (HWND)dw_window_get_data(hWnd, "_dw_comboentry")) != NULLHANDLE) + dw_window_get_pos_size(entry, 0, 0, 0, &thumbheight); + + if(!thumbheight) + thumbheight = WinQuerySysValue(HWND_DESKTOP, SV_CYVSCROLLARROW); + + /* Add 6 because it has a thick border like the entryfield */ + thumbheight += 6; + + color = (ULONG)dw_window_get_data(parent, "_dw_fore"); + dw_window_get_pos_size(hWnd, 0, 0, &width, &height); + + if(height > thumbheight) + { + hpsPaint = WinGetPS(hWnd); + if(color) + GpiSetColor(hpsPaint, _internal_color(color-1)); + else + GpiSetColor(hpsPaint, CLR_PALEGRAY); + + ptl.x = ptl.y = 0; + GpiMove(hpsPaint, &ptl); + + ptl.x = width; + ptl.y = height - thumbheight; + GpiBox(hpsPaint, DRO_FILL, &ptl, 0, 0); + + WinReleasePS(hpsPaint); + } + } + break; + } + if(oldproc) + return oldproc(hWnd, msg, mp1, mp2); + + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +void _GetPPFont(HWND hwnd, char *buff) +{ + ULONG AttrFound; + BYTE AttrValue[128]; + ULONG cbRetLen; + + cbRetLen = WinQueryPresParam(hwnd, + PP_FONTNAMESIZE, + 0, + &AttrFound, + sizeof(AttrValue), + &AttrValue, + QPF_NOINHERIT); + + if(PP_FONTNAMESIZE == AttrFound && cbRetLen) + { + memcpy(buff, AttrValue, cbRetLen); + } +} + +int _HandleScroller(HWND handle, int pos, int which) +{ + MPARAM res; + int min, max, page; + + if(which == SB_SLIDERTRACK) + return pos; + + pos = dw_scrollbar_get_pos(handle); + res = WinSendMsg(handle, SBM_QUERYRANGE, 0, 0); + + min = SHORT1FROMMP(res); + max = SHORT2FROMMP(res); + page = (int)dw_window_get_data(handle, "_dw_scrollbar_visible"); + + switch(which) + { + case SB_LINEUP: + pos = pos - 1; + if(pos < min) + pos = min; + dw_scrollbar_set_pos(handle, pos); + return pos; + case SB_LINEDOWN: + pos = pos + 1; + if(pos > max) + pos = max; + dw_scrollbar_set_pos(handle, pos); + return pos; + case SB_PAGEUP: + pos = pos - page; + if(pos < min) + pos = min; + dw_scrollbar_set_pos(handle, pos); + return pos; + case SB_PAGEDOWN: + pos = pos + page; + if(pos > max) + pos = max; + dw_scrollbar_set_pos(handle, pos); + return pos; + } + return -1; +} + +void _clear_emphasis(void) +{ + if(hwndEmph && WinIsWindow(dwhab, hwndEmph) && pCoreEmph) + WinSendMsg(hwndEmph, CM_SETRECORDEMPHASIS, pCoreEmph, MPFROM2SHORT(FALSE, CRA_SOURCE)); + hwndEmph = NULLHANDLE; + pCoreEmph = NULL; +} + +/* Find the desktop window handle */ +HWND _menu_owner(HWND handle) +{ + HWND menuowner = NULLHANDLE, lastowner = (HWND)dw_window_get_data(handle, "_dw_owner"); + int menubar = (int)dw_window_get_data(handle, "_dw_menubar"); + + /* Find the toplevel window */ + while(!menubar && (menuowner = (HWND)dw_window_get_data(lastowner, "_dw_owner")) != NULLHANDLE) + { + menubar = (int)dw_window_get_data(lastowner, "_dw_menubar"); + lastowner = menuowner; + } + if(menuowner && menubar) + { + HWND client = WinWindowFromID(menuowner, FID_CLIENT); + + return client ? client : menuowner; + } + return NULLHANDLE; +} + +MRESULT EXPENTRY _run_event(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + int result = -1; + SignalHandler *tmp = Root; + ULONG origmsg = msg; + + if(msg == WM_BUTTON2DOWN || msg == WM_BUTTON3DOWN) + msg = WM_BUTTON1DOWN; + if(msg == WM_BUTTON2UP || msg == WM_BUTTON3UP) + msg = WM_BUTTON1UP; + if(msg == WM_VSCROLL || msg == WM_HSCROLL) + msg = WM_CONTROL; + + /* Find any callbacks for this function */ + while(tmp) + { + if(tmp->message == msg || msg == WM_CONTROL || tmp->message == WM_USER+1) + { + switch(msg) + { + case WM_SETFOCUS: + { + if((mp2 && tmp->message == WM_SETFOCUS) || (!mp2 && tmp->message == WM_USER+1)) + { + int (* API setfocusfunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction; + + if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd) + { + result = setfocusfunc(tmp->window, tmp->data); + tmp = NULL; + } + } + } + break; + case WM_TIMER: + { + int (* API timerfunc)(void *) = (int (* API)(void *))tmp->signalfunction; + if(tmp->id == (int)mp1) + { + if(!timerfunc(tmp->data)) + dw_timer_disconnect(tmp->id); + tmp = NULL; + } + result = 0; + } + break; + case WM_SIZE: + { + int (* API sizefunc)(HWND, int, int, void *) = (int (* API)(HWND, int, int, void *))tmp->signalfunction; + + if((hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd) && SHORT1FROMMP(mp2) && SHORT2FROMMP(mp2)) + { + result = sizefunc(tmp->window, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2), tmp->data); + tmp = NULL; + } + } + break; + case WM_BUTTON1DOWN: + { + POINTS pts = (*((POINTS*)&mp1)); + int (* API buttonfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction; + + if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window) + { + int button = 0; + + switch(origmsg) + { + case WM_BUTTON1DOWN: + button = 1; + break; + case WM_BUTTON2DOWN: + button = 2; + break; + case WM_BUTTON3DOWN: + button = 3; + break; + } + + result = buttonfunc(tmp->window, pts.x, WinQueryWindow(tmp->window, QW_PARENT) == HWND_DESKTOP ? dw_screen_height() - pts.y : _get_height(tmp->window) - pts.y, button, tmp->data); + tmp = NULL; + } + } + break; + case WM_BUTTON1UP: + { + POINTS pts = (*((POINTS*)&mp1)); + int (* API buttonfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction; + + if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window) + { + int button = 0; + + switch(origmsg) + { + case WM_BUTTON1UP: + button = 1; + break; + case WM_BUTTON2UP: + button = 2; + break; + case WM_BUTTON3UP: + button = 3; + break; + } + + result = buttonfunc(tmp->window, pts.x, WinQueryWindow(tmp->window, QW_PARENT) == HWND_DESKTOP ? dw_screen_height() - pts.y : _get_height(tmp->window) - pts.y, button, tmp->data); + tmp = NULL; + } + } + break; + case WM_MOUSEMOVE: + { + int (* API motionfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction; + + if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window) + { + int keys = 0; + SHORT x = SHORT1FROMMP(mp1), y = SHORT2FROMMP(mp1); + + if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000) + keys = DW_BUTTON1_MASK; + if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000) + keys |= DW_BUTTON2_MASK; + if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000) + keys |= DW_BUTTON3_MASK; + + result = motionfunc(tmp->window, x, _get_height(hWnd) - y, keys, tmp->data); + tmp = NULL; + } + } + break; + case WM_CHAR: + { + int (* API keypressfunc)(HWND, char, int, int, void *) = (int (* API)(HWND, char, int, int, void *))tmp->signalfunction; + + if((hWnd == tmp->window || _toplevel_window(hWnd) == tmp->window) && !(SHORT1FROMMP(mp1) & KC_KEYUP)) + { + int vk; + char ch = 0; + + if(SHORT1FROMMP(mp1) & KC_CHAR) + ch = (char)SHORT1FROMMP(mp2); + if(SHORT1FROMMP(mp1) & KC_VIRTUALKEY) + vk = SHORT2FROMMP(mp2); + else + vk = SHORT1FROMMP(mp2) + 128; + + /* This is a hack to fix shift presses showing + * up as tabs! + */ + if(ch == '\t' && !(SHORT1FROMMP(mp1) & KC_CHAR)) + { + ch = 0; + vk = VK_SHIFT; + } + + result = keypressfunc(tmp->window, ch, vk, + SHORT1FROMMP(mp1) & (KC_ALT | KC_SHIFT | KC_CTRL), tmp->data); + tmp = NULL; + } + } + break; + case WM_CLOSE: + { + int (* API closefunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction; + + if(hWnd == tmp->window || hWnd == WinWindowFromID(tmp->window, FID_CLIENT)) + { + result = closefunc(tmp->window, tmp->data); + if(result) + result = FALSE; + tmp = NULL; + } + } + break; + case WM_PAINT: + { + HPS hps; + DWExpose exp; + int (* API exposefunc)(HWND, DWExpose *, void *) = (int (* API)(HWND, DWExpose *, void *))tmp->signalfunction; + RECTL rc; + + if(hWnd == tmp->window) + { + int height = _get_height(hWnd); + + hps = WinBeginPaint(hWnd, 0L, &rc); + exp.x = rc.xLeft; + exp.y = height - rc.yTop - 1; + exp.width = rc.xRight - rc. xLeft; + exp.height = rc.yTop - rc.yBottom; + result = exposefunc(hWnd, &exp, tmp->data); + WinEndPaint(hps); + } + } + break; + case WM_COMMAND: + { + int (* API clickfunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction; + ULONG command = COMMANDMSG(&msg)->cmd; + + if(tmp->id && command == tmp->id) + { + HWND menuowner = _menu_owner(tmp->window); + + if(menuowner == hWnd || menuowner == NULLHANDLE) + { + result = clickfunc(tmp->window, tmp->data); + tmp = NULL; + } + } + else if(tmp->window < 65536 && command == tmp->window) + { + result = clickfunc(popup ? popup : tmp->window, tmp->data); + tmp = NULL; + } + } + break; + case WM_CONTROL: + if(origmsg == WM_VSCROLL || origmsg == WM_HSCROLL || tmp->message == SHORT2FROMMP(mp1) || + (tmp->message == SLN_SLIDERTRACK && SHORT2FROMMP(mp1) == SLN_CHANGE)) + { + int svar = SLN_SLIDERTRACK; + int id = SHORT1FROMMP(mp1); + HWND notifyhwnd = dw_window_from_id(hWnd, id); + + if(origmsg == WM_CONTROL) + svar = SHORT2FROMMP(mp1); + + switch(svar) + { + case CN_ENTER: + { + int (* API containerselectfunc)(HWND, char *, void *) = (int (* API)(HWND, char *, void *))tmp->signalfunction; + char *text = NULL; + + if(mp2) + { + PRECORDCORE pre; + + pre = ((PNOTIFYRECORDENTER)mp2)->pRecord; + if(pre) + text = pre->pszIcon; + } + + if(tmp->window == notifyhwnd) + { + result = containerselectfunc(tmp->window, text, tmp->data); + tmp = NULL; + } + } + break; + case CN_EXPANDTREE: + { + int (* API treeexpandfunc)(HWND, HTREEITEM, void *) = (int (* API)(HWND, HTREEITEM, void *))tmp->signalfunction; + + if(tmp->window == notifyhwnd) + { + result = treeexpandfunc(tmp->window, (HTREEITEM)mp2, tmp->data); + tmp = NULL; + } + } + break; + case CN_CONTEXTMENU: + { + int (* API containercontextfunc)(HWND, char *, int, int, void *, void *) = (int (* API)(HWND, char *, int, int, void *, void *))tmp->signalfunction; + char *text = NULL; + void *user = NULL; + LONG x,y; + + if(mp2) + { + PCNRITEM pci; + + pci = (PCNRITEM)mp2; + + text = pci->rc.pszIcon; + user = pci->user; + } + + dw_pointer_query_pos(&x, &y); + + if(tmp->window == notifyhwnd) + { + int container = (int)dw_window_get_data(tmp->window, "_dw_container"); + + if(mp2) + { + if(!container) + { + NOTIFYRECORDEMPHASIS pre; + + dw_tree_item_select(tmp->window, (HTREEITEM)mp2); + pre.pRecord = mp2; + pre.fEmphasisMask = CRA_CURSORED; + pre.hwndCnr = tmp->window; + _run_event(hWnd, WM_CONTROL, MPFROM2SHORT(0, CN_EMPHASIS), (MPARAM)&pre); + pre.pRecord->flRecordAttr |= CRA_CURSORED; + } + else + { + if(pCoreEmph) + _clear_emphasis(); + hwndEmph = tmp->window; + pCoreEmph = mp2; + WinSendMsg(tmp->window, CM_SETRECORDEMPHASIS, mp2, MPFROM2SHORT(TRUE, CRA_SOURCE)); + } + } + result = containercontextfunc(tmp->window, text, x, y, tmp->data, user); + tmp = NULL; + } + } + break; + case CN_EMPHASIS: + { + PNOTIFYRECORDEMPHASIS pre = (PNOTIFYRECORDEMPHASIS)mp2; + static int emph_recurse = 0; + + if(!emph_recurse) + { + emph_recurse = 1; + + if(mp2) + { + if(tmp->window == pre->hwndCnr) + { + PCNRITEM pci = (PCNRITEM)pre->pRecord; + + if(pci && pre->fEmphasisMask & CRA_CURSORED && (pci->rc.flRecordAttr & CRA_CURSORED)) + { + int (* API treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = (int (* API)(HWND, HTREEITEM, char *, void *, void *))tmp->signalfunction; + + if(dw_window_get_data(tmp->window, "_dw_container")) + result = treeselectfunc(tmp->window, 0, pci->rc.pszIcon, tmp->data, 0); + else + { + if(lasthcnr == tmp->window && lastitem == (HWND)pci) + { + lasthcnr = 0; + lastitem = 0; + } + else + { + lasthcnr = tmp->window; + lastitem = (HWND)pci; + result = treeselectfunc(tmp->window, (HTREEITEM)pci, pci->rc.pszIcon, tmp->data, pci->user); + } + } + tmp = NULL; + } + } + } + emph_recurse = 0; + } + } + break; + case LN_SELECT: + { + char classbuf[100]; + + WinQueryClassName(tmp->window, 99, classbuf); + + if(strncmp(classbuf, "#38", 4) == 0) + { + int (* API valuechangedfunc)(HWND, int, void *) = (int (* API)(HWND, int, void *))tmp->signalfunction; + + if(tmp->window == hWnd || tmp->window == notifyhwnd) + { + static int lastvalue = -1; + static HWND lasthwnd = NULLHANDLE; + int ulValue = (int)WinSendMsg(tmp->window, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0); + if(lastvalue != ulValue || lasthwnd != tmp->window) + { + result = valuechangedfunc(tmp->window, ulValue, tmp->data); + lastvalue = ulValue; + lasthwnd = tmp->window; + } + tmp = NULL; + } + } + else + { + int (* API listboxselectfunc)(HWND, int, void *) = (int (* API )(HWND, int, void *))tmp->signalfunction; + static int _recursing = 0; + + if(_recursing == 0 && (tmp->window == notifyhwnd || (!id && tmp->window == (HWND)mp2))) + { + char buf1[500]; + int index = dw_listbox_selected(tmp->window); + + dw_listbox_get_text(tmp->window, index, buf1, 500); + + _recursing = 1; + + if(id && strncmp(classbuf, "#2", 3)==0) + { + char *buf2; + + buf2 = dw_window_get_text(tmp->window); + + /* This is to make sure the listboxselect function doesn't + * get called if the user is modifying the entry text. + */ + if(buf2 && *buf2 && *buf1 && strncmp(buf1, buf2, 500) == 0) + result = listboxselectfunc(tmp->window, index, tmp->data); + + if(buf2) + free(buf2); + } + else + result = listboxselectfunc(tmp->window, index, tmp->data); + + _recursing = 0; + tmp = NULL; + } + } + } + break; + case SLN_SLIDERTRACK: + { + int (* API valuechangedfunc)(HWND, int, void *) = (int (* API)(HWND, int, void *))tmp->signalfunction; + + if(origmsg == WM_CONTROL) + { + /* Handle Slider control */ + if(tmp->window == hWnd || tmp->window == notifyhwnd) + { + static int lastvalue = -1; + static HWND lasthwnd = NULLHANDLE; + int ulValue = (int)WinSendMsg(tmp->window, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0); + if(lastvalue != ulValue || lasthwnd != tmp->window) + { + dw_window_set_data(tmp->window, "_dw_slider_value", (void *)ulValue); + result = valuechangedfunc(tmp->window, ulValue, tmp->data); + lastvalue = ulValue; + lasthwnd = tmp->window; + } + tmp = NULL; + } + } + else + { + /* Handle scrollbar control */ + if(tmp->window > 65535 && tmp->window == notifyhwnd) + { + int pos = _HandleScroller(tmp->window, (int)SHORT1FROMMP(mp2), (int)SHORT2FROMMP(mp2));; + + if(pos > -1) + { + dw_window_set_data(tmp->window, "_dw_scrollbar_value", (void *)pos); + result = valuechangedfunc(tmp->window, pos, tmp->data); + } + result = 0; + tmp = NULL; + } + } + } + break; + case BKN_PAGESELECTED: + { + PAGESELECTNOTIFY *psn = (PAGESELECTNOTIFY *)mp2; + + if(psn && tmp->window == psn->hwndBook) + { + int (* API switchpagefunc)(HWND, unsigned long, void *) = (int (* API)(HWND, unsigned long, void *))tmp->signalfunction; + + result = switchpagefunc(tmp->window, psn->ulPageIdNew, tmp->data); + tmp = NULL; + } + } + break; + } + } + break; + } + } + + if(tmp) + tmp = tmp->next; + + } + return (MRESULT)result; +} + +/* Gets a DW_RGB value from the three spinbuttons */ +unsigned long _dw_color_spin_get(HWND window) +{ + HWND button = (HWND)dw_window_get_data(window, "_dw_red_spin"); + long red, green, blue; + + red = dw_spinbutton_get_pos(button); + button = (HWND)dw_window_get_data(window, "_dw_green_spin"); + green = dw_spinbutton_get_pos(button); + button = (HWND)dw_window_get_data(window, "_dw_blue_spin"); + blue = dw_spinbutton_get_pos(button); + + return DW_RGB(red, green, blue); +} + +/* Set the three spinbuttons from a DW_RGB value */ +void _dw_color_spin_set(HWND window, unsigned long value) +{ + HWND button = (HWND)dw_window_get_data(window, "_dw_red_spin"); + dw_window_set_data(window, "_dw_updating", (void *)1); + dw_spinbutton_set_pos(button, DW_RED_VALUE(value)); + button = (HWND)dw_window_get_data(window, "_dw_green_spin"); + dw_spinbutton_set_pos(button, DW_GREEN_VALUE(value)); + button = (HWND)dw_window_get_data(window, "_dw_blue_spin"); + dw_spinbutton_set_pos(button, DW_BLUE_VALUE(value)); + dw_window_set_data(window, "_dw_updating", NULL); +} + +/* Sets the color selection control to be a DW_RGB value */ +void _dw_col_set(HWND col, unsigned long value) +{ + WinSendMsg(col, 0x0602, MPFROMLONG(_os2_color(value)), 0); + if(!IS_WARP4()) + WinSendMsg(col, 0x1384, MPFROMLONG(_os2_color(value)), 0); +} + +/* Handles control messages sent to the box (owner). */ +MRESULT EXPENTRY _controlproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + Box *blah = WinQueryWindowPtr(hWnd, QWP_USER); + + switch(msg) + { + case WM_MOUSEMOVE: + if(_wndproc(hWnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + break; + case WM_VSCROLL: + case WM_HSCROLL: + if(_run_event(hWnd, msg, mp1, mp2)) + { + HWND window = WinWindowFromID(hWnd, (ULONG)mp1); + _HandleScroller(window, (int)SHORT1FROMMP(mp2), (int)SHORT2FROMMP(mp2)); + } + break; + /* Handles Color Selection control messages */ + case 0x0601: + case 0x130C: + { + HWND window = (HWND)dw_window_get_data(hWnd, "_dw_window"); + unsigned long val = (unsigned long)mp1; + + if(window) + _dw_color_spin_set(window, DW_RGB((val & 0xFF0000) >> 16, (val & 0xFF00) >> 8, val & 0xFF)); + } + break; + case WM_CONTROL: + if((SHORT2FROMMP(mp1) == SPBN_CHANGE || SHORT2FROMMP(mp1) == SPBN_ENDSPIN)) + { + HWND window = (HWND)dw_window_get_data(hWnd, "_dw_window"); + + if(window && !dw_window_get_data(window, "_dw_updating")) + { + unsigned long val = _dw_color_spin_get(window); + HWND col = (HWND)dw_window_get_data(window, "_dw_col"); + + _dw_col_set(col, val); + } + } + _run_event(hWnd, msg, mp1, mp2); + break; + } + + if(blah && blah->oldproc) + return blah->oldproc(hWnd, msg, mp1, mp2); + + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +/* The main window procedure for Dynamic Windows, all the resizing code is done here. */ +MRESULT EXPENTRY _wndproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + int result = -1; + static int command_active = 0; + void (* API windowfunc)(PVOID) = 0L; + + if(!command_active) + { + /* Make sure we don't end up in infinite recursion */ + command_active = 1; + + result = (int)_run_event(hWnd, msg, mp1, mp2); + + command_active = 0; + } + + /* Now that any handlers are done... do normal processing */ + switch( msg ) + { + case WM_ERASEBACKGROUND: + return 0; + + case WM_PAINT: + { + HPS hps; + RECTL rc; + + hps = WinBeginPaint( hWnd, 0L, &rc ); + WinEndPaint( hps ); + break; + } + + case WM_SIZE: + { + Box *mybox = (Box *)WinQueryWindowPtr(hWnd, QWP_USER); + + if(!SHORT1FROMMP(mp2) && !SHORT2FROMMP(mp2)) + return (MPARAM)TRUE; + + if(mybox && mybox->flags != DW_MINIMIZED) + { + /* Hide the window when recalculating to reduce + * CPU load. + */ + WinShowWindow(hWnd, FALSE); + + if(mybox->items) + WinSetWindowPos(mybox->items[0].hwnd, HWND_TOP, 0, 0, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2), SWP_MOVE | SWP_SIZE); + + _do_resize(mybox, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2)); + + WinShowWindow(hWnd, TRUE); + } + } + break; + case WM_MINMAXFRAME: + { + Box *mybox = (Box *)WinQueryWindowPtr(hWnd, QWP_USER); + SWP *swp = (SWP *)mp1; + + if(mybox && (swp->fl & SWP_MINIMIZE)) + mybox->flags = DW_MINIMIZED; + + if(mybox && (swp->fl & SWP_RESTORE)) + { + if(!mybox->titlebar && mybox->hwndtitle) + WinSetParent(mybox->hwndtitle, HWND_OBJECT, FALSE); + mybox->flags = 0; + } + + if(mybox && (swp->fl & (SWP_MAXIMIZE | SWP_RESTORE))) + { + int z; + SWP swp2; + + WinQueryWindowPos(swp->hwnd, &swp2); + + if(swp2.cx == swp->cx && swp2.cy == swp->cy) + return FALSE; + + mybox->flags = 0; + + /* Hide the window when recalculating to reduce + * CPU load. + */ + WinShowWindow(hWnd, FALSE); + + _do_resize(mybox, swp->cx, swp->cy); + + if(mybox->count == 1 && mybox->items[0].type == TYPEBOX) + { + mybox = (Box *)WinQueryWindowPtr(mybox->items[0].hwnd, QWP_USER); + + for(z=0;z<mybox->count;z++) + _check_resize_notebook(mybox->items[z].hwnd); + + } + + WinShowWindow(hWnd, TRUE); + } + } + break; + case WM_CONTROL: + switch(SHORT2FROMMP(mp1)) + { + case BKN_PAGESELECTEDPENDING: + { + PAGESELECTNOTIFY *psn = (PAGESELECTNOTIFY *)mp2; + HWND pagehwnd = (HWND)WinSendMsg(psn->hwndBook, BKM_QUERYPAGEWINDOWHWND, MPFROMLONG(psn->ulPageIdNew), 0); + Box *pagebox = (Box *)WinQueryWindowPtr(pagehwnd, QWP_USER); + long x, y; + unsigned long width, height; + RECTL rc; + + if(pagebox && psn->ulPageIdNew != psn->ulPageIdCur) + { + dw_window_get_pos_size(psn->hwndBook, &x, &y, &width, &height); + + rc.xLeft = x; + rc.yBottom = y; + rc.xRight = x + width; + rc.yTop = y + height; + + WinSendMsg(psn->hwndBook, BKM_CALCPAGERECT, (MPARAM)&rc, (MPARAM)TRUE); + + _do_resize(pagebox, rc.xRight - rc.xLeft, rc.yTop - rc.yBottom); + } + } + break; + } + break; + case WM_CLOSE: + if(result == -1) + { + dw_window_destroy(WinQueryWindow(hWnd, QW_PARENT)); + return (MRESULT)TRUE; + } + break; + case WM_MOUSEMOVE: + { + HPOINTER pointer; + + if((pointer = (HPOINTER)dw_window_get_data(hWnd, "_dw_pointer")) || + (pointer = (HPOINTER)dw_window_get_data(_toplevel_window(hWnd), "_dw_pointer"))) + { + WinSetPointer(HWND_DESKTOP, pointer); + return MRFROMSHORT(TRUE); + } + } + return MRFROMSHORT(FALSE); + case WM_USER: + windowfunc = (void (* API)(void *))mp1; + + if(windowfunc) + windowfunc((void *)mp2); + break; + case WM_CHAR: + if(SHORT1FROMMP(mp2) == '\t') + { + if(CHARMSG(&msg)->fs & KC_SHIFT) + _shift_focus_back(hWnd); + else + _shift_focus(hWnd); + return FALSE; + } + break; + case WM_DESTROY: + { + HWND parent = WinQueryWindow(hWnd, QW_PARENT); + + /* Free memory before destroying */ + if(parent && WinWindowFromID(parent, FID_CLIENT) == hWnd) + _free_window_memory(parent); + else + _free_window_memory(hWnd); + } + break; + case WM_MENUEND: + /* Delay removing the signal until we've executed + * the signal handler. + */ + WinPostMsg(hWnd, WM_USER+2, mp1, mp2); + break; + case WM_DDE_INITIATEACK: + /* aswer dde server */ + hwndTrayServer = (HWND)mp1; + break; + case WM_BUTTON1DOWN | 0x2000: + case WM_BUTTON2DOWN | 0x2000: + case WM_BUTTON3DOWN | 0x2000: + case WM_BUTTON1UP | 0x2000: + case WM_BUTTON2UP | 0x2000: + case WM_BUTTON3UP | 0x2000: + if(hwndTaskBar) + result = (int)_run_event(hwndTaskBar, msg & ~0x2000, mp1, mp2); + break; + case WM_USER+2: + _clear_emphasis(); + if(dw_window_get_data((HWND)mp2, "_dw_popup")) + _free_menu_data((HWND)mp2); + break; + } + + if(result != -1) + return (MRESULT)result; + else + return WinDefWindowProc(hWnd, msg, mp1, mp2); +} + +void _changebox(Box *thisbox, int percent, int type) +{ + int z; + + for(z=0;z<thisbox->count;z++) + { + if(thisbox->items[z].type == TYPEBOX) + { + Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER); + _changebox(tmp, percent, type); + } + else + { + if(type == DW_HORZ) + { + if(thisbox->items[z].hsize == SIZEEXPAND) + thisbox->items[z].width = (int)(((float)thisbox->items[z].origwidth) * (((float)percent)/((float)100.0))); + } + else + { + if(thisbox->items[z].vsize == SIZEEXPAND) + thisbox->items[z].height = (int)(((float)thisbox->items[z].origheight) * (((float)percent)/((float)100.0))); + } + } + } +} + +void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y) +{ + float ratio = (float)percent/(float)100.0; + HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_topleft"); + HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright"); + Box *tmp = WinQueryWindowPtr(handle1, QWP_USER); + + WinShowWindow(handle1, FALSE); + WinShowWindow(handle2, FALSE); + + if(type == DW_HORZ) + { + int newx = (int)((float)x * ratio) - (SPLITBAR_WIDTH/2); + + WinSetWindowPos(handle1, NULLHANDLE, 0, 0, newx, y, SWP_MOVE | SWP_SIZE); + _do_resize(tmp, newx - 1, y - 1); + + dw_window_set_data(hwnd, "_dw_start", (void *)newx); + + tmp = WinQueryWindowPtr(handle2, QWP_USER); + + newx = x - newx - SPLITBAR_WIDTH; + + WinSetWindowPos(handle2, NULLHANDLE, x - newx, 0, newx, y, SWP_MOVE | SWP_SIZE); + _do_resize(tmp, newx - 1, y - 1); + } + else + { + int newy = (int)((float)y * ratio) - (SPLITBAR_WIDTH/2); + + WinSetWindowPos(handle1, NULLHANDLE, 0, y - newy, x, newy, SWP_MOVE | SWP_SIZE); + _do_resize(tmp, x - 1, newy - 1); + + tmp = WinQueryWindowPtr(handle2, QWP_USER); + + newy = y - newy - SPLITBAR_WIDTH; + + WinSetWindowPos(handle2, NULLHANDLE, 0, 0, x, newy, SWP_MOVE | SWP_SIZE); + _do_resize(tmp, x - 1, newy - 1); + + dw_window_set_data(hwnd, "_dw_start", (void *)newy); + } + + WinShowWindow(handle1, TRUE); + WinShowWindow(handle2, TRUE); +} + + +/* This handles any activity on the splitbars (sizers) */ +MRESULT EXPENTRY _splitwndproc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + switch (msg) + { + case WM_ACTIVATE: + case WM_SETFOCUS: + return (MRESULT)(FALSE); + + case WM_PAINT: + { + HPS hps; + POINTL ptl[2]; + RECTL rcl; + int type = (int)dw_window_get_data(hwnd, "_dw_type"); + int start = (int)dw_window_get_data(hwnd, "_dw_start"); + + hps = WinBeginPaint(hwnd, 0, 0); + + WinQueryWindowRect(hwnd, &rcl); + + if(type == DW_HORZ) + { + ptl[0].x = rcl.xLeft + start; + ptl[0].y = rcl.yBottom; + ptl[1].x = rcl.xRight + start + 3; + ptl[1].y = rcl.yTop; + } + else + { + ptl[0].x = rcl.xLeft; + ptl[0].y = rcl.yBottom + start; + ptl[1].x = rcl.xRight; + ptl[1].y = rcl.yTop + start + 3; + } + + + GpiSetColor(hps, CLR_PALEGRAY); + GpiMove(hps, &ptl[0]); + GpiBox(hps, DRO_OUTLINEFILL, &ptl[1], 0, 0); + WinEndPaint(hps); + } + return MRFROMSHORT(FALSE); + + case WM_MOUSEMOVE: + { + int type = (int)dw_window_get_data(hwnd, "_dw_type"); + + if(type == DW_HORZ) + WinSetPointer(HWND_DESKTOP, + WinQuerySysPointer(HWND_DESKTOP, + SPTR_SIZEWE, + FALSE)); + else + WinSetPointer(HWND_DESKTOP, + WinQuerySysPointer(HWND_DESKTOP, + SPTR_SIZENS, + FALSE)); + } + return MRFROMSHORT(FALSE); + case WM_BUTTON1DOWN: + { + APIRET rc; + RECTL rclFrame; + RECTL rclBounds; + float *percent = (float *)dw_window_get_data(hwnd, "_dw_percent"); + int type = (int)dw_window_get_data(hwnd, "_dw_type"); + int start = (int)dw_window_get_data(hwnd, "_dw_start"); + + WinQueryWindowRect(hwnd, &rclFrame); + WinQueryWindowRect(hwnd, &rclBounds); + + WinMapWindowPoints(hwnd, HWND_DESKTOP, + (PPOINTL)&rclBounds, 2); + + + if(type == DW_HORZ) + { + rclFrame.xLeft = start; + rclFrame.xRight = start + SPLITBAR_WIDTH; + } + else + { + rclFrame.yBottom = start; + rclFrame.yTop = start + SPLITBAR_WIDTH; + } + + if(percent) + { + rc = _TrackRectangle(hwnd, &rclFrame, &rclBounds); + + if(rc == TRUE) + { + int width = (rclBounds.xRight - rclBounds.xLeft); + int height = (rclBounds.yTop - rclBounds.yBottom); + + if(type == DW_HORZ) + { + start = rclFrame.xLeft - rclBounds.xLeft; + if(width - SPLITBAR_WIDTH > 1 && start < width - SPLITBAR_WIDTH) + *percent = ((float)start / (float)(width - SPLITBAR_WIDTH)) * 100.0; + } + else + { + start = rclFrame.yBottom - rclBounds.yBottom; + if(height - SPLITBAR_WIDTH > 1 && start < height - SPLITBAR_WIDTH) + *percent = 100.0 - (((float)start / (float)(height - SPLITBAR_WIDTH)) * 100.0); + } + _handle_splitbar_resize(hwnd, *percent, type, width, height); + _handle_splitbar_resize(hwnd, *percent, type, width, height); + } + } + } + return MRFROMSHORT(FALSE); + } + return WinDefWindowProc(hwnd, msg, mp1, mp2); +} + +/* Function: BubbleProc + * Abstract: Subclass procedure for bubble help + */ +MRESULT EXPENTRY _BubbleProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + MRESULT res; + PFNWP proc = (PFNWP)WinQueryWindowPtr(hwnd, QWL_USER); + + if(proc) + res = proc(hwnd, msg, mp1, mp2); + else + res = WinDefWindowProc(hwnd, msg, mp1, mp2); + + if(msg == WM_PAINT) + { + POINTL ptl; + HPS hpsTemp; + RECTL rcl; + int height, width; + + WinQueryWindowRect(hwnd, &rcl); + height = rcl.yTop - rcl.yBottom - 1; + width = rcl.xRight - rcl.xLeft - 1; + + /* Draw a border around the bubble help */ + hpsTemp = WinGetPS(hwnd); + GpiSetColor(hpsTemp, CLR_BLACK); + ptl.x = ptl.y = 0; + GpiMove(hpsTemp, &ptl); + ptl.x = 0; + ptl.y = height; + GpiLine(hpsTemp, &ptl); + ptl.x = ptl.y = 0; + GpiMove(hpsTemp, &ptl); + ptl.y = 0; + ptl.x = width; + GpiLine(hpsTemp, &ptl); + ptl.x = width; + ptl.y = height; + GpiMove(hpsTemp, &ptl); + ptl.x = 0; + ptl.y = height; + GpiLine(hpsTemp, &ptl); + ptl.x = width; + ptl.y = height; + GpiMove(hpsTemp, &ptl); + ptl.y = 0; + ptl.x = width; + GpiLine(hpsTemp, &ptl); + WinReleasePS(hpsTemp); + } + return res; +} + +MRESULT EXPENTRY _button_draw(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2, PFNWP oldproc, int indent) +{ + HPIXMAP pixmap = (HPIXMAP)dw_window_get_data(hwnd, "_dw_hpixmap"); + HPIXMAP disable = (HPIXMAP)dw_window_get_data(hwnd, "_dw_hpixmap_disabled"); + HPOINTER icon = (HPOINTER)dw_window_get_data(hwnd, "_dw_button_icon"); + MRESULT res; + unsigned long width, height; + int x = 5, y = 5; + + dw_window_get_pos_size(hwnd, NULL, NULL, &width, &height); + + if(!oldproc) + res = WinDefWindowProc(hwnd, msg, mp1, mp2); + res = oldproc(hwnd, msg, mp1, mp2); + + if(icon) + { + ULONG halftone = DP_NORMAL; + HPS hps = WinGetPS(hwnd); + POINTERINFO pi; + int cx, cy; + + if(dw_window_get_data(hwnd, "_dw_disabled")) + halftone = DP_HALFTONED; + + cx = width - 10; + cy = height - 10; + + if(WinQueryPointerInfo(icon, &pi)) + { + BITMAPINFOHEADER sl; + int newcx = cx, newcy = cy; + + /* Check the mini icon first */ + if(GpiQueryBitmapParameters(pi.hbmMiniColor, &sl)) + { + if(sl.cx && sl.cy && cx > sl.cx && cy > sl.cy) + { + newcx = sl.cx; + newcy = sl.cy; + } + } + /* Check the normal icon second */ + if(GpiQueryBitmapParameters(pi.hbmColor, &sl)) + { + if(sl.cx && sl.cy && cx > sl.cx && cy > sl.cy) + { + newcx = sl.cx; + newcy = sl.cy; + } + } + cx = newcx; cy = newcy; + x = (width - cx)/2; + y = (height - cy)/2; + } + WinStretchPointer(hps, x + indent, y - indent, cx, cy, icon, halftone); + WinReleasePS(hps); + } + else if(pixmap) + { + x = (width - pixmap->width)/2; + y = (height - pixmap->height)/2; + + if(disable && dw_window_get_data(hwnd, "_dw_disabled")) + dw_pixmap_bitblt(hwnd, 0, x + indent, y + indent, pixmap->width, pixmap->height, 0, disable, 0, 0); + else + dw_pixmap_bitblt(hwnd, 0, x + indent, y + indent, pixmap->width, pixmap->height, 0, pixmap, 0, 0); + } + return res; +} + +/* Function: BtProc + * Abstract: Subclass procedure for buttons + */ + +MRESULT EXPENTRY _BtProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + BubbleButton *bubble; + PFNWP oldproc; + + bubble = (BubbleButton *)WinQueryWindowPtr(hwnd, QWL_USER); + + if(!bubble) + return WinDefWindowProc(hwnd, msg, mp1, mp2); + + oldproc = bubble->pOldProc; + + switch(msg) + { + case WM_MOUSEMOVE: + if(_wndproc(hwnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + break; + case WM_PAINT: + return _button_draw(hwnd, msg, mp1, mp2, oldproc, 0); + case BM_SETHILITE: + return _button_draw(hwnd, msg, mp1, mp2, oldproc, (int)mp1); + case WM_SETFOCUS: + if(mp2) + _run_event(hwnd, msg, mp1, mp2); + else + WinSendMsg(hwnd, BM_SETDEFAULT, 0, 0); + break; + case WM_BUTTON1DOWN: + case WM_BUTTON2DOWN: + case WM_BUTTON3DOWN: + case WM_BUTTON1DBLCLK: + case WM_BUTTON2DBLCLK: + case WM_BUTTON3DBLCLK: + if(dw_window_get_data(hwnd, "_dw_disabled")) + return (MRESULT)FALSE; + break; + case WM_BUTTON1UP: + { + SignalHandler *tmp = Root; + + if(WinIsWindowEnabled(hwnd) && !dw_window_get_data(hwnd, "_dw_disabled")) + { + /* Find any callbacks for this function */ + while(tmp) + { + if(tmp->message == WM_COMMAND) + { + /* Make sure it's the right window, and the right ID */ + if(tmp->window == hwnd) + { + /* Due to the fact that if we run the function + * here, finishing actions on the button will occur + * after we run the signal handler. So we post the + * message so the button can finish what it needs to + * do before we run our handler. + */ + WinPostMsg(hwnd, WM_USER, (MPARAM)tmp, 0); + tmp = NULL; + } + } + if(tmp) + tmp= tmp->next; + } + } + } + break; + case WM_USER: + { + SignalHandler *tmp = (SignalHandler *)mp1; + int (* API clickfunc)(HWND, void *) = NULL; + + if(tmp) + { + clickfunc = (int (* API)(HWND, void *))tmp->signalfunction; + + clickfunc(tmp->window, tmp->data); + } + } + break; + case WM_CHAR: + { + /* A button press should also occur for an ENTER or SPACE press + * while the button has the active input focus. + */ + if(SHORT1FROMMP(mp2) == '\r' || SHORT1FROMMP(mp2) == ' ') + { + SignalHandler *tmp = Root; + + /* Find any callbacks for this function */ + while(tmp) + { + if(tmp->message == WM_COMMAND) + { + /* Make sure it's the right window, and the right ID */ + if(tmp->window == hwnd) + { + WinPostMsg(hwnd, WM_USER, (MPARAM)tmp, 0); + tmp = NULL; + } + } + if(tmp) + tmp= tmp->next; + } + } + if(SHORT1FROMMP(mp2) == '\t') + { + if(CHARMSG(&msg)->fs & KC_SHIFT) + _shift_focus_back(hwnd); + else + _shift_focus(hwnd); + 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); + return FALSE; + } + else if(!(CHARMSG(&msg)->fs & KC_KEYUP) && (CHARMSG(&msg)->vkey == VK_RIGHT || CHARMSG(&msg)->vkey == VK_DOWN)) + { + _shift_focus(hwnd); + return FALSE; + } + } + break; + case 0x041f: + if (hwndBubble) + { + WinDestroyWindow(hwndBubble); + hwndBubble = 0; + } + break; + + case 0x041e: + + if(!*bubble->bubbletext) + break; + + if(hwndBubble) + { + WinDestroyWindow(hwndBubble); + hwndBubble = 0; + } + + if(!hwndBubble) + { + HPS hpsTemp = 0; + LONG lHight; + LONG lWidth; + POINTL txtPointl[TXTBOX_COUNT]; + POINTL ptlWork = {0,0}; + ULONG ulColor = CLR_YELLOW; + void *blah; + + hwndBubbleLast = hwnd; + hwndBubble = WinCreateWindow(HWND_DESKTOP, + WC_STATIC, + "", + SS_TEXT | + DT_CENTER | + DT_VCENTER, + 0,0,0,0, + HWND_DESKTOP, + HWND_TOP, + 0, + NULL, + NULL); + + WinSetPresParam(hwndBubble, + PP_FONTNAMESIZE, + strlen(DefaultFont)+1, + DefaultFont); + + + WinSetPresParam(hwndBubble, + PP_BACKGROUNDCOLORINDEX, + sizeof(ulColor), + &ulColor); + + WinSetWindowText(hwndBubble, + bubble->bubbletext); + + WinMapWindowPoints(hwnd, HWND_DESKTOP, &ptlWork, 1); + + hpsTemp = WinGetPS(hwndBubble); + GpiQueryTextBox(hpsTemp, + strlen(bubble->bubbletext), + bubble->bubbletext, + TXTBOX_COUNT, + txtPointl); + WinReleasePS(hpsTemp); + + lWidth = txtPointl[TXTBOX_TOPRIGHT].x - + txtPointl[TXTBOX_TOPLEFT ].x + 8; + + lHight = txtPointl[TXTBOX_TOPLEFT].y - + txtPointl[TXTBOX_BOTTOMLEFT].y + 8; + + ptlWork.y -= lHight; + + blah = (void *)WinSubclassWindow(hwndBubble, _BubbleProc); + + if(blah) + WinSetWindowPtr(hwndBubble, QWP_USER, blah); + + WinSetWindowPos(hwndBubble, + HWND_TOP, + ptlWork.x, + ptlWork.y, + lWidth, + lHight, + SWP_SIZE | SWP_MOVE | SWP_SHOW); + } + break; + } + + if(!oldproc) + return WinDefWindowProc(hwnd, msg, mp1, mp2); + return oldproc(hwnd, msg, mp1, mp2); +} + +MRESULT EXPENTRY _RendProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + int res = 0; + res = (int)_run_event(hwnd, msg, mp1, mp2); + switch(msg) + { + case WM_MOUSEMOVE: + if(_wndproc(hwnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + break; + case WM_BUTTON1DOWN: + case WM_BUTTON2DOWN: + case WM_BUTTON3DOWN: + if(res == -1) + WinSetFocus(HWND_DESKTOP, hwnd); + else if(res) + return (MPARAM)TRUE; + } + return WinDefWindowProc(hwnd, msg, mp1, mp2); +} + +MRESULT EXPENTRY _TreeProc(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_MOUSEMOVE: + if(_wndproc(hwnd, msg, mp1, mp2)) + return MPFROMSHORT(FALSE); + break; + case WM_PAINT: + { + HPS hps; + RECTL rcl; + POINTL ptl[2]; + + if(oldproc) + oldproc(hwnd, msg, mp1, mp2); + + hps = WinBeginPaint(hwnd, 0, 0); + WinQueryWindowRect(hwnd, &rcl); + ptl[0].x = rcl.xLeft + 1; + ptl[0].y = rcl.yBottom + 1; + ptl[1].x = rcl.xRight - 1; + ptl[1].y = rcl.yTop - 1; + + GpiSetColor(hps, CLR_BLACK); + GpiMove(hps, &ptl[0]); + GpiBox(hps, DRO_OUTLINE, &ptl[1], 0, 0); + WinEndPaint(hps); + } + return MRFROMSHORT(FALSE); + case WM_SETFOCUS: + _run_event(hwnd, msg, mp1, mp2); + break; + case WM_CHAR: + if(SHORT1FROMMP(mp2) == '\t') + { + if(CHARMSG(&msg)->fs & KC_SHIFT) + _shift_focus_back(hwnd); + else + _shift_focus(hwnd); + return FALSE; + } + break; + } + + _run_event(hwnd, msg, mp1, mp2); + + if(oldproc) + return oldproc(hwnd, msg, mp1, mp2); + + return WinDefWindowProc(hwnd, msg, mp1, mp2); +} + +/* + * Initializes the Dynamic Windows engine. + * Parameters: + * newthread: True if this is the only thread. + * False if there is already a message loop running. + */ +int API dw_init(int newthread, int argc, char *argv[]) +{ + APIRET rc; + char objnamebuf[300] = ""; + + argc = argc; /* keep compiler happy */ + argv = argv; /* keep compiler happy */ + if(newthread) + { + dwhab = WinInitialize(0); + dwhmq = WinCreateMsgQueue(dwhab, 0); + } + + rc = WinRegisterClass(dwhab, ClassName, _wndproc, CS_SIZEREDRAW | CS_CLIPCHILDREN, 32); + rc = WinRegisterClass(dwhab, SplitbarClassName, _splitwndproc, 0L, 32); + rc = WinRegisterClass(dwhab, ScrollClassName, _scrollwndproc, 0L, 32); + + /* Get the OS/2 version. */ + DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_MS_COUNT,(void *)aulBuffer, 4*sizeof(ULONG)); + + desktop = WinQueryDesktopWindow(dwhab, NULLHANDLE); + + if(!IS_WARP4()) + DefaultFont = strdup("8.Helv"); + else + DefaultFont = strdup(DefaultFont); + + /* This is a window that hangs around as long as the + * application does and handles menu messages. + */ + hwndApp = dw_window_new(HWND_OBJECT, "", 0); + /* Attempt to locate a tray server */ + WinDdeInitiate(hwndApp, "SystrayServer", "TRAY", NULL); + + DosLoadModule(objnamebuf, sizeof(objnamebuf), "WPCONFIG", &wpconfig); + + return rc; +} + +/* + * Runs a message loop for Dynamic Windows. + */ +void API dw_main(void) +{ + QMSG qmsg; + + _dwtid = dw_thread_id(); + + while(WinGetMsg(dwhab, &qmsg, 0, 0, 0)) + { + if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) + _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); + WinDispatchMsg(dwhab, &qmsg); + } + + WinDestroyMsgQueue(dwhmq); + WinTerminate(dwhab); +} + +/* + * Runs a message loop for Dynamic Windows, for a period of milliseconds. + * Parameters: + * milliseconds: Number of milliseconds to run the loop for. + */ +void API dw_main_sleep(int milliseconds) +{ + QMSG qmsg; +#ifdef __EMX__ + struct timeval tv, start; + + gettimeofday(&start, NULL); + gettimeofday(&tv, NULL); + + while(((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000) <= milliseconds) + { + if(WinPeekMsg(dwhab, &qmsg, 0, 0, 0, PM_NOREMOVE)) + { + WinGetMsg(dwhab, &qmsg, 0, 0, 0); + if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) + _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); + WinDispatchMsg(dwhab, &qmsg); + } + else + DosSleep(1); + gettimeofday(&tv, NULL); + } +#else + double start = (double)clock(); + + while(((clock() - start) / (CLOCKS_PER_SEC/1000)) <= milliseconds) + { + if(WinPeekMsg(dwhab, &qmsg, 0, 0, 0, PM_NOREMOVE)) + { + WinGetMsg(dwhab, &qmsg, 0, 0, 0); + if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) + _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); + WinDispatchMsg(dwhab, &qmsg); + } + else + DosSleep(1); + } +#endif +} + +/* + * Processes a single message iteration and returns. + */ +void API dw_main_iteration(void) +{ + QMSG qmsg; + + _dwtid = dw_thread_id(); + + if(WinGetMsg(dwhab, &qmsg, 0, 0, 0)) + { + if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) + _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); + WinDispatchMsg(dwhab, &qmsg); + } +} + +/* + * Free's memory allocated by dynamic windows. + * Parameters: + * ptr: Pointer to dynamic windows allocated + * memory to be free()'d. + */ +void API dw_free(void *ptr) +{ + free(ptr); +} + +/* + * Allocates and initializes a dialog struct. + * Parameters: + * data: User defined data to be passed to functions. + */ +DWDialog * API dw_dialog_new(void *data) +{ + DWDialog *tmp = malloc(sizeof(DWDialog)); + + tmp->eve = dw_event_new(); + dw_event_reset(tmp->eve); + tmp->data = data; + tmp->done = FALSE; + tmp->result = NULL; + + return tmp; +} + +/* + * Accepts a dialog struct and returns the given data to the + * initial called of dw_dialog_wait(). + * Parameters: + * dialog: Pointer to a dialog struct aquired by dw_dialog_new). + * result: Data to be returned by dw_dialog_wait(). + */ +int API dw_dialog_dismiss(DWDialog *dialog, void *result) +{ + dialog->result = result; + dw_event_post(dialog->eve); + dialog->done = TRUE; + return 0; +} + +/* + * Accepts a dialog struct waits for dw_dialog_dismiss() to be + * called by a signal handler with the given dialog struct. + * Parameters: + * dialog: Pointer to a dialog struct aquired by dw_dialog_new). + */ +void * API dw_dialog_wait(DWDialog *dialog) +{ + QMSG qmsg; + void *tmp; + + while (WinGetMsg(dwhab, &qmsg, 0, 0, 0)) + { + if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE) + _run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); + WinDispatchMsg(dwhab, &qmsg); + if(dialog->done) + break; + } + dw_event_close(&dialog->eve); + tmp = dialog->result; + free(dialog); + return tmp; +} + +/* + * Displays a debug message on the console... + * Parameters: + * format: printf style format string. + * ...: Additional variables for use in the format. + */ +void API dw_debug(char *format, ...) +{ + va_list args; + char outbuf[1024]; + + va_start(args, format); + vsprintf(outbuf, format, args); + va_end(args); + + fprintf(stderr, "%s", outbuf); +} + +/* + * Displays a Message Box with given text and title.. + * Parameters: + * title: The title of the message box. + * flags: flags to indicate buttons and icon + * format: printf style format string. + * ...: Additional variables for use in the format. + */ +int API dw_messagebox(char *title, int flags, char *format, ...) +{ + va_list args; + char outbuf[1024]; + int rc; + + va_start(args, format); + vsprintf(outbuf, format, args); + va_end(args); + + rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, outbuf, title, 0, flags | MB_MOVEABLE); + if(rc == MBID_OK) + return DW_MB_RETURN_OK; + else if(rc == MBID_YES) + return DW_MB_RETURN_YES; + else if(rc == MBID_NO) + return DW_MB_RETURN_NO; + else if(rc == MBID_CANCEL) + return DW_MB_RETURN_CANCEL; + else return 0; +} + +/* + * Makes the window topmost. + * Parameters: + * handle: The window handle to make topmost. + */ +int API dw_window_raise(HWND handle) +{ + return WinSetWindowPos(handle, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER); +} + +/* + * Makes the window bottommost. + * Parameters: + * handle: The window handle to make bottommost. + */ +int API dw_window_lower(HWND handle) +{ + return WinSetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER); +} + +/* + * Makes the window visible. + * Parameters: + * handle: The window handle to make visible. + */ +int API dw_window_show(HWND handle) +{ + int rc = WinSetWindowPos(handle, NULLHANDLE, 0, 0, 0, 0, SWP_SHOW); + HSWITCH hswitch; + SWCNTRL swcntrl; + + _fix_button_owner(_toplevel_window(handle), 0); + WinSetFocus(HWND_DESKTOP, handle); + _initial_focus(handle); + + /* If this window has a switch list entry make sure it is visible */ + hswitch = WinQuerySwitchHandle(handle, 0); + if(hswitch) + { + WinQuerySwitchEntry(hswitch, &swcntrl); + swcntrl.uchVisibility = SWL_VISIBLE; + WinChangeSwitchEntry(hswitch, &swcntrl); + } + if(WinWindowFromID(handle, FID_CLIENT)) + { + WindowData *blah = WinQueryWindowPtr(handle, QWP_USER); + + if(blah && !(blah->flags & DW_OS2_NEW_WINDOW)) + { + ULONG cx = dw_screen_width(), cy = dw_screen_height(); + int newx, newy, changed = 0; + SWP swp; + + blah->flags |= DW_OS2_NEW_WINDOW; + + WinQueryWindowPos(handle, &swp); + + newx = swp.x; + newy = swp.y; + + if((swp.x+swp.cx) > cx) + { + newx = (cx - swp.cx)/2; + changed = 1; + } + if((swp.y+swp.cy) > cy) + { + newy = (cy - swp.cy)/2; + changed = 1; + } + if(changed) + WinSetWindowPos(handle, NULLHANDLE, newx, newy, 0, 0, SWP_MOVE); + } + } + return rc; +} + +/* + * Minimizes or Iconifies a top-level window. + * Parameters: + * handle: The window handle to minimize. + */ +int API dw_window_minimize(HWND handle) +{ + HWND hwndclient = WinWindowFromID(handle, FID_CLIENT); + + if(hwndclient) + { + Box *box = (Box *)WinQueryWindowPtr(hwndclient, QWP_USER); + + if(box) + { + if(!box->titlebar && box->hwndtitle) + WinSetParent(box->hwndtitle, handle, FALSE); + } + } + + return WinSetWindowPos(handle, NULLHANDLE, 0, 0, 0, 0, SWP_MINIMIZE); +} + +/* + * Makes the window invisible. + * Parameters: + * handle: The window handle to make visible. + */ +int API dw_window_hide(HWND handle) +{ + HSWITCH hswitch; + SWCNTRL swcntrl; + + /* If this window has a switch list entry make sure it is invisible */ + hswitch = WinQuerySwitchHandle(handle, 0); + if(hswitch) + { + WinQuerySwitchEntry(hswitch, &swcntrl); + swcntrl.uchVisibility = SWL_INVISIBLE; + WinChangeSwitchEntry(hswitch, &swcntrl); + } + return WinShowWindow(handle, FALSE); +} + +/* + * Destroys a window and all of it's children. + * Parameters: + * handle: The window handle to destroy. + */ +int API dw_window_destroy(HWND handle) +{ + HWND frame, menu, parent = WinQueryWindow(handle, QW_PARENT); + Box *thisbox = WinQueryWindowPtr(parent, QWP_USER); + + if(!handle) + return -1; + + frame = (HWND)dw_window_get_data(handle, "_dw_combo_box"); + + if((menu = WinWindowFromID(handle, FID_MENU)) != NULLHANDLE) + _free_menu_data(menu); + + /* If it is a desktop window let WM_DESTROY handle it */ + if(parent != desktop) + { + /* If the parent box has items... + * try to remove it from the layout + */ + if(thisbox && thisbox->count) + { + int z, index = -1; + Item *tmpitem, *thisitem = thisbox->items; + + for(z=0;z<thisbox->count;z++) + { + if(thisitem[z].hwnd == handle) + index = z; + } + + if(index == -1) + return 0; + + tmpitem = malloc(sizeof(Item)*(thisbox->count-1)); + + /* Copy all but the current entry to the new list */ + for(z=0;z<index;z++) + { + tmpitem[z] = thisitem[z]; + } + for(z=index+1;z<thisbox->count;z++) + { + tmpitem[z-1] = thisitem[z]; + } + + thisbox->items = tmpitem; + free(thisitem); + thisbox->count--; + } + _free_window_memory(frame ? frame : handle); + } + return WinDestroyWindow(frame ? frame : handle); +} + +/* Causes entire window to be invalidated and redrawn. + * Parameters: + * handle: Toplevel window handle to be redrawn. + */ +void API dw_window_redraw(HWND handle) +{ + HWND client = WinWindowFromID(handle, FID_CLIENT); + HWND window = client ? client : handle; + Box *mybox = (Box *)WinQueryWindowPtr(window, QWP_USER); + + _fix_button_owner(_toplevel_window(handle), 0); + if(window && mybox) + { + unsigned long width, height; + + dw_window_get_pos_size(window, NULL, NULL, &width, &height); + + if(mybox->items) + WinSetWindowPos(mybox->items[0].hwnd, HWND_TOP, 0, 0, width, height, SWP_MOVE | SWP_SIZE); + + WinShowWindow(client && mybox->items ? mybox->items[0].hwnd : handle, FALSE); + _do_resize(mybox, width, height); + WinShowWindow(client && mybox->items ? mybox->items[0].hwnd : handle, TRUE); + } +} + +/* + * Changes a window's parent to newparent. + * Parameters: + * handle: The window handle to destroy. + * newparent: The window's new parent window. + */ +void API dw_window_reparent(HWND handle, HWND newparent) +{ + HWND blah = WinWindowFromID(newparent, FID_CLIENT); + WinSetParent(handle, blah ? blah : newparent, TRUE); +} + +/* Allows the user to choose a font using the system's font chooser dialog. + * Parameters: + * currfont: current font + * Returns: + * A malloced buffer with the selected font or NULL on error. + */ +char * API dw_font_choose(char *currfont) +{ + FONTDLG fd = { 0 }; + char *buf = calloc(1,100); + int size = 9; + + /* Fill in the family name if possible */ + if(currfont) + { + char *name = strchr(currfont, '.'); + if(name) + { + int newsize = atoi(currfont); + if(newsize > 0) + size = newsize; + name++; + strcpy(buf, name); + strcpy(fd.fAttrs.szFacename, name); + } + else + { + strcpy(buf, currfont); + strcpy(fd.fAttrs.szFacename, currfont); + } + } + + /* Fill in the font dialog struct */ + fd.cbSize = sizeof(fd); + fd.hpsScreen = WinGetScreenPS(HWND_DESKTOP); + fd.pszTitle = "Choose Font"; + fd.clrFore = CLR_BLACK; + fd.clrBack = CLR_WHITE; + fd.pszFamilyname = buf; + fd.usFamilyBufLen = 100; + fd.fxPointSize = MAKEFIXED(size,0); + fd.fl = FNTS_INITFROMFATTRS; + + /* Show the dialog and wait for a response */ + if(!WinFontDlg(HWND_DESKTOP, HWND_OBJECT, &fd) || fd.lReturn != DID_OK) + { + WinReleasePS(fd.hpsScreen); + free(buf); + return NULL; + } + WinReleasePS(fd.hpsScreen); + /* Figure out what the user selected and return that */ + size = FIXEDINT(fd.fxPointSize); + sprintf(buf, "%d.%s", size, fd.fAttrs.szFacename); + return buf; +} + +/* + * Sets the default font used on text based widgets. + * Parameters: + * fontname: Font name in Dynamic Windows format. + */ +void API dw_font_set_default(char *fontname) +{ + char *oldfont = DefaultFont; + + DefaultFont = strdup(fontname); + free(oldfont); +} + +/* + * Sets the font used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * fontname: Name and size of the font in the form "size.fontname" + */ +int API dw_window_set_font(HWND handle, char *fontname) +{ + HWND group = (HWND)dw_window_get_data(handle, "_dw_buddy"); + return WinSetPresParam(group ? group : handle, PP_FONTNAMESIZE, strlen(fontname)+1, fontname); +} + +/* + * Gets the font used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * fontname: Name and size of the font in the form "size.fontname" + */ +char * API dw_window_get_font(HWND handle) +{ + char *str = (char *)alloca(50); + HWND group = (HWND)dw_window_get_data(handle, "_dw_buddy"); + if(str && WinQueryPresParam(group ? group : handle, PP_FONTNAMESIZE, 0, NULL, 50, str, QPF_NOINHERIT)) + return strdup(str); + return NULL; +} + +/* Internal version */ +int _dw_window_set_color(HWND handle, ULONG fore, ULONG back) +{ + if((fore & DW_RGB_COLOR) == DW_RGB_COLOR) + { + RGB2 rgb2; + + rgb2.bBlue = DW_BLUE_VALUE(fore); + rgb2.bGreen = DW_GREEN_VALUE(fore); + rgb2.bRed = DW_RED_VALUE(fore); + rgb2.fcOptions = 0; + + WinSetPresParam(handle, PP_FOREGROUNDCOLOR, sizeof(RGB2), &rgb2); + + } + else if(fore != DW_CLR_DEFAULT) + { + fore = _internal_color(fore); + + WinSetPresParam(handle, PP_FOREGROUNDCOLORINDEX, sizeof(ULONG), &fore); + } + if((back & DW_RGB_COLOR) == DW_RGB_COLOR) + { + RGB2 rgb2; + + rgb2.bBlue = DW_BLUE_VALUE(back); + rgb2.bGreen = DW_GREEN_VALUE(back); + rgb2.bRed = DW_RED_VALUE(back); + rgb2.fcOptions = 0; + + WinSetPresParam(handle, PP_BACKGROUNDCOLOR, sizeof(RGB2), &rgb2); + return 0; + } + else if(back != DW_CLR_DEFAULT) + { + back = _internal_color(back); + + WinSetPresParam(handle, PP_BACKGROUNDCOLORINDEX, sizeof(ULONG), &back); + } + return 0; +} +/* + * Sets the colors used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * fore: Foreground color in DW_RGB format or a default color index. + * back: Background color in DW_RGB format or a default color index. + */ +int API dw_window_set_color(HWND handle, ULONG fore, ULONG back) +{ + dw_window_set_data(handle, "_dw_fore", (void *)(fore+1)); + dw_window_set_data(handle, "_dw_back", (void *)(back+1)); + + return _dw_window_set_color(handle, fore, back); +} + +/* + * Sets the font used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * border: Size of the window border in pixels. + */ +int API dw_window_set_border(HWND handle, int border) +{ + WinSendMsg(handle, WM_SETBORDERSIZE, MPFROMSHORT(border), MPFROMSHORT(border)); + return 0; +} + +/* + * Captures the mouse input to this window. + * Parameters: + * handle: Handle to receive mouse input. + */ +void API dw_window_capture(HWND handle) +{ + WinSetCapture(HWND_DESKTOP, handle); +} + +/* + * Releases previous mouse capture. + */ +void API dw_window_release(void) +{ + WinSetCapture(HWND_DESKTOP, NULLHANDLE); +} + +/* + * Tracks this window movement. + * Parameters: + * handle: Handle to frame to be tracked. + */ +void API dw_window_track(HWND handle) +{ + WinSendMsg(handle, WM_TRACKFRAME, MPFROMSHORT(TF_MOVE), 0); +} + +/* + * Changes the appearance of the mouse pointer. + * Parameters: + * handle: Handle to widget for which to change. + * cursortype: ID of the pointer you want. + */ +void API dw_window_set_pointer(HWND handle, int pointertype) +{ + HPOINTER pointer = pointertype < 65535 ? + WinQuerySysPointer(HWND_DESKTOP, pointertype, FALSE) + : (HPOINTER)pointertype; + + if(!pointertype) + dw_window_set_data(handle, "_dw_pointer", 0); + else + { + WinSetPointer(HWND_DESKTOP, pointer); + + if(handle != HWND_DESKTOP) + dw_window_set_data(handle, "_dw_pointer", (void *)pointer); + } +} + +/* + * Create a new Window Frame. + * Parameters: + * owner: The Owner's window handle or HWND_DESKTOP. + * title: The Window title. + * flStyle: Style flags, see the PM reference. + */ +HWND API dw_window_new(HWND hwndOwner, char *title, ULONG flStyle) +{ + HWND hwndframe; + Box *newbox = calloc(1, sizeof(Box)); + WindowData *blah = calloc(1, sizeof(WindowData)); + ULONG winStyle = 0L; + + newbox->pad = 0; + newbox->type = DW_VERT; + newbox->count = 0; + + flStyle |= FCF_NOBYTEALIGN; + + if(flStyle & DW_FCF_TITLEBAR) + newbox->titlebar = 1; + else + flStyle |= FCF_TITLEBAR; + + if(!(flStyle & FCF_SHELLPOSITION)) + blah->flags |= DW_OS2_NEW_WINDOW; + + if(flStyle & WS_MAXIMIZED) + { + winStyle |= WS_MAXIMIZED; + flStyle &= ~WS_MAXIMIZED; + } + if(flStyle & WS_MINIMIZED) + { + winStyle |= WS_MINIMIZED; + flStyle &= ~WS_MINIMIZED; + } + + hwndframe = WinCreateStdWindow(hwndOwner, winStyle, &flStyle, ClassName, title, 0L, NULLHANDLE, 0L, &newbox->hwnd); + newbox->hwndtitle = WinWindowFromID(hwndframe, FID_TITLEBAR); + if(!newbox->titlebar && newbox->hwndtitle) + WinSetParent(newbox->hwndtitle, HWND_OBJECT, FALSE); + blah->oldproc = WinSubclassWindow(hwndframe, _sizeproc); + WinSetWindowPtr(hwndframe, QWP_USER, blah); + WinSetWindowPtr(newbox->hwnd, QWP_USER, newbox); + + return hwndframe; +} + +/* + * Create a new Box to be packed. + * Parameters: + * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). + * pad: Number of pixels to pad around the box. + */ +HWND API dw_box_new(int type, int pad) +{ + Box *newbox = calloc(1, sizeof(Box)); + + newbox->pad = pad; + newbox->type = type; + newbox->count = 0; + newbox->grouphwnd = NULLHANDLE; + + newbox->hwnd = WinCreateWindow(HWND_OBJECT, + WC_FRAME, + NULL, + WS_VISIBLE | WS_CLIPCHILDREN | + FS_NOBYTEALIGN, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + 0L, + NULL, + NULL); + + newbox->oldproc = WinSubclassWindow(newbox->hwnd, _controlproc); + WinSetWindowPtr(newbox->hwnd, QWP_USER, newbox); + dw_window_set_color(newbox->hwnd, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY); + return newbox->hwnd; +} + +/* + * Create a new scroll Box to be packed. + * Parameters: + * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). + * pad: Number of pixels to pad around the box. + */ +HWND API dw_scrollbox_new(int type, int pad) +{ + HWND hwndframe, box = dw_box_new(type, pad); + HWND client, tmpbox = dw_box_new(DW_VERT, 0); + Box *blah = calloc(sizeof(Box), 1); + dw_box_pack_start(tmpbox, box, 1, 1, TRUE, TRUE, 0); + hwndframe = WinCreateWindow(HWND_OBJECT, ScrollClassName, "", WS_VISIBLE | WS_CLIPCHILDREN, + 0, 0, 2000, 1000, NULLHANDLE, HWND_TOP, 0, NULL, NULL); + WinCreateWindow(hwndframe, WC_SCROLLBAR, "", WS_VISIBLE | SBS_AUTOTRACK | SBS_VERT, + 0,0,2000,1000, hwndframe, HWND_TOP, FID_VERTSCROLL, NULL, NULL); + WinCreateWindow(hwndframe, WC_SCROLLBAR, "", WS_VISIBLE | SBS_AUTOTRACK | SBS_HORZ, + 0,0,2000,1000, hwndframe, HWND_TOP, FID_HORZSCROLL, NULL, NULL); + client = WinCreateWindow(hwndframe, WC_FRAME, "", WS_VISIBLE | WS_CLIPCHILDREN, + 0,0,2000,1000, NULLHANDLE, HWND_TOP, FID_CLIENT, NULL, NULL); + WinSetParent(tmpbox, client, FALSE); + WinSetWindowPtr(client, QWP_USER, blah); + dw_window_set_data(hwndframe, "_dw_resizebox", (void *)tmpbox); + dw_window_set_data(hwndframe, "_dw_box", (void *)box); + dw_window_set_color(hwndframe, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY); + dw_window_set_color(client, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY); + return hwndframe; +} + +/* + * Returns the position of the scrollbar in the scrollbox + * Parameters: + * handle: Handle to the scrollbox to be queried. + * orient: The vertical or horizontal scrollbar. + */ +int API dw_scrollbox_get_pos( HWND handle, int orient ) +{ + HWND scroll; + + if(orient == DW_VERT) + { + scroll = WinWindowFromID(handle, FID_VERTSCROLL); + } + else + { + scroll = WinWindowFromID(handle, FID_HORZSCROLL); + } + return (int)WinSendMsg(scroll, SBM_QUERYPOS, 0, 0); +} + +/* + * Gets the range for the scrollbar in the scrollbox. + * Parameters: + * handle: Handle to the scrollbox to be queried. + * orient: The vertical or horizontal scrollbar. + */ +int API dw_scrollbox_get_range( HWND handle, int orient ) +{ + HWND scroll; + + if(orient == DW_VERT) + { + scroll = WinWindowFromID(handle, FID_VERTSCROLL); + } + else + { + scroll = WinWindowFromID(handle, FID_HORZSCROLL); + } + return SHORT2FROMMP(WinSendMsg(scroll, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), 0)); +} + +/* + * Create a new Group Box to be packed. + * Parameters: + * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). + * pad: Number of pixels to pad around the box. + * title: Text to be displayined in the group outline. + */ +HWND API dw_groupbox_new(int type, int pad, char *title) +{ + Box *newbox = calloc(1, sizeof(Box)); + newbox->pad = pad; + newbox->type = type; + newbox->count = 0; + + newbox->hwnd = WinCreateWindow(HWND_OBJECT, + WC_FRAME, + NULL, + WS_VISIBLE | + FS_NOBYTEALIGN, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + 0L, + NULL, + NULL); + + newbox->grouphwnd = WinCreateWindow(newbox->hwnd, + WC_STATIC, + title, + WS_VISIBLE | SS_GROUPBOX | + WS_GROUP, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + 0L, + NULL, + NULL); + + WinSetWindowPtr(newbox->hwnd, QWP_USER, newbox); + dw_window_set_color(newbox->hwnd, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY); + dw_window_set_color(newbox->grouphwnd, DW_CLR_BLACK, DW_CLR_PALEGRAY); + dw_window_set_font(newbox->grouphwnd, DefaultFont); + dw_window_set_data(newbox->hwnd, "_dw_buddy", (void *)newbox->grouphwnd); + return newbox->hwnd; +} + +/* + * Create a new MDI Frame to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id or 0L. + */ +HWND API dw_mdi_new(unsigned long id) +{ + HWND hwndframe; + ULONG back = CLR_DARKGRAY; + + hwndframe = WinCreateWindow(HWND_OBJECT, + WC_FRAME, + NULL, + WS_VISIBLE | WS_CLIPCHILDREN | + FS_NOBYTEALIGN, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + /* Make the MDI Client area the same color as Windows and Unix */ + WinSetPresParam(hwndframe, PP_BACKGROUNDCOLORINDEX, sizeof(ULONG), &back); + return hwndframe; +} + +/* + * Create a bitmap object to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_bitmap_new(ULONG id) +{ + return WinCreateWindow(HWND_OBJECT, + WC_STATIC, + NULL, + WS_VISIBLE | SS_TEXT, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); +} + +/* + * Create a notebook object to be packed. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HWND API dw_notebook_new(ULONG id, int top) +{ + ULONG flags; + HWND tmp; + + if(top) + flags = BKS_MAJORTABTOP; + else + flags = BKS_MAJORTABBOTTOM; + + tmp = WinCreateWindow(HWND_OBJECT, + WC_NOTEBOOK, + NULL, + WS_VISIBLE | +#ifdef BKS_TABBEDDIALOG + BKS_TABBEDDIALOG | +#endif + flags, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + + /* Fix tab sizes on Warp 3 */ + if(!IS_WARP4()) + { + /* best sizes to be determined by trial and error */ + WinSendMsg(tmp, BKM_SETDIMENSIONS,MPFROM2SHORT(102, 28), MPFROMSHORT( BKA_MAJORTAB)); + } + + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Create a menu object to be popped up. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HMENUI API dw_menu_new(ULONG id) +{ + HMENUI tmp = WinCreateWindow(HWND_OBJECT, + WC_MENU, + NULL, + WS_VISIBLE, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + return tmp; +} + +/* + * Create a menubar on a window. + * Parameters: + * location: Handle of a window frame to be attached to. + */ +HMENUI API dw_menubar_new(HWND location) +{ + HMENUI tmp = WinCreateWindow(location, + WC_MENU, + NULL, + WS_VISIBLE | MS_ACTIONBAR, + 0,0,2000,1000, + location, + HWND_TOP, + FID_MENU, + NULL, + NULL); + dw_window_set_data(tmp, "_dw_owner", (void *)location); + dw_window_set_data(tmp, "_dw_menubar", (void *)location); + return tmp; +} + +/* + * Destroys a menu created with dw_menubar_new or dw_menu_new. + * Parameters: + * menu: Handle of a menu. + */ +void API dw_menu_destroy(HMENUI *menu) +{ + if(menu) + WinDestroyWindow(*menu); +} + +/* Internal function to make sure menu ID isn't in use */ +int _menuid_allocated(int id) +{ + SignalHandler *tmp = Root; + + while(tmp) + { + if(tmp->id == id) + return TRUE; + tmp = tmp->next; + } + return FALSE; +} + +/* + * Adds a menuitem or submenu to an existing menu. + * Parameters: + * menu: The handle the the existing menu. + * title: The title text on the menu item to be added. + * id: An ID to be used for message passing. + * flags: Extended attributes to set on the menu. + * end: If TRUE memu is positioned at the end of the menu. + * check: If TRUE menu is "check"able. + * flags: Extended attributes to set on the menu. + * submenu: Handle to an existing menu to be a submenu or NULL. + */ +HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu) +{ + MENUITEM miSubMenu; + char buffer[30]; + int is_checked, is_disabled; + + if ( !menux || !WinIsWindow(dwhab, menux) ) + return NULLHANDLE; + + if ( end ) + miSubMenu.iPosition=MIT_END; + else + miSubMenu.iPosition=0; + /* + * Handle flags + */ + miSubMenu.afAttribute = 0; + is_checked = (flags & DW_MIS_CHECKED) ? 1 : 0; + if ( is_checked ) + miSubMenu.afAttribute |= MIA_CHECKED; + is_disabled = (flags & DW_MIS_DISABLED) ? 1 : 0; + if ( is_disabled ) + miSubMenu.afAttribute |= MIA_DISABLED; + + if (title && *title) + { + /* Code to autogenerate a menu ID if not specified or invalid + * First pool is smaller for transient popup menus + */ + if(id == (ULONG)-1) + { + static ULONG tempid = 61000; + + tempid++; + id = tempid; + + if(tempid > 65500) + tempid = 61000; + } + /* Special internal case */ + else if(id > 60000 && check == -1) + { + check = 0; + } + /* Second pool is larger for more static windows */ + else if(!id || id >= 30000) + { + static ULONG menuid = 30000; + + do + { + menuid++; + if(menuid > 60000) + menuid = 30000; + } + while(_menuid_allocated(menuid)); + id = menuid; + } + miSubMenu.afStyle = MIS_TEXT; + } + else + miSubMenu.afStyle = MIS_SEPARATOR; + miSubMenu.id=id; + miSubMenu.hwndSubMenu = submenu; + miSubMenu.hItem=NULLHANDLE; + + WinSendMsg(menux, MM_INSERTITEM, MPFROMP(&miSubMenu), MPFROMP(title)); + + sprintf(buffer, "_dw_id%d", (int)id); + dw_window_set_data(hwndApp, buffer, (void *)menux); + sprintf(buffer, "_dw_checkable%ld", id); + dw_window_set_data( hwndApp, buffer, (void *)check ); + sprintf(buffer, "_dw_ischecked%ld", id); + dw_window_set_data( hwndApp, buffer, (void *)is_checked ); + sprintf(buffer, "_dw_isdisabled%ld", id); + dw_window_set_data( hwndApp, buffer, (void *)is_disabled ); + + if ( submenu ) + dw_window_set_data(submenu, "_dw_owner", (void *)menux); + return (HWND)id; +} + +/* + * Sets the state of a menu item check. + * Deprecated; use dw_menu_item_set_state() + * Parameters: + * menu: The handle the the existing menu. + * id: Menuitem id. + * check: TRUE for checked FALSE for not checked. + */ +void API dw_menu_item_set_check(HMENUI menux, unsigned long id, int check) +{ + if ( check ) + WinSendMsg(menux, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE),MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)); + else + WinSendMsg(menux, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE),MPFROM2SHORT(MIA_CHECKED, 0)); +} + +/* + * Sets the state of a menu item. + * Parameters: + * menu: The handle to the existing menu. + * id: Menuitem id. + * flags: DW_MIS_ENABLED/DW_MIS_DISABLED + * DW_MIS_CHECKED/DW_MIS_UNCHECKED + */ +void API dw_menu_item_set_state( HMENUI menux, unsigned long id, unsigned long state) +{ + char buffer1[30],buffer2[30]; + int check; + int disabled; + USHORT fAttribute=0; + + sprintf( buffer1, "_dw_ischecked%ld", id ); + check = (int)dw_window_get_data( hwndApp, buffer1 ); + sprintf( buffer2, "_dw_isdisabled%ld", id ); + disabled = (int)dw_window_get_data( hwndApp, buffer2 ); + + if ( (state & DW_MIS_CHECKED) || (state & DW_MIS_UNCHECKED) ) + { + /* + * If we are changing state of "checked" base our setting on the passed flag... + */ + if ( state & DW_MIS_CHECKED ) + { + fAttribute |= MIA_CHECKED; + check = 1; + } + else + { + check = 0; + } + } + else + { + /* + * ...otherwise base our setting on the current "checked" state. + */ + if ( check ) + { + fAttribute |= MIA_CHECKED; + } + } + if ( (state & DW_MIS_ENABLED) || (state & DW_MIS_DISABLED) ) + { + if ( state & DW_MIS_DISABLED ) + { + fAttribute |= MIA_DISABLED; + disabled = 1; + } + else + { + disabled = 0; + } + } + else + { + /* + * ...otherwise base our setting on the current "disabled" state. + */ + if ( disabled ) + { + fAttribute |= MIA_DISABLED; + } + } + WinSendMsg( menux, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE), MPFROM2SHORT( MIA_CHECKED|MIA_DISABLED, fAttribute ) ); + /* + * Keep our internal checked state consistent + */ + dw_window_set_data( hwndApp, buffer1, (void *)check ); + dw_window_set_data( hwndApp, buffer2, (void *)disabled ); +} + +/* + * Pops up a context menu at given x and y coordinates. + * Parameters: + * menu: The handle the the existing menu. + * parent: Handle to the window initiating the popup. + * x: X coordinate. + * y: Y coordinate. + */ +void API dw_menu_popup(HMENUI *menu, HWND parent, int x, int y) +{ + if(menu) + { + popup = parent; + dw_window_set_data(*menu, "_dw_popup", (void *)1); + WinPopupMenu(HWND_DESKTOP, parent, *menu, x, dw_screen_height() - y, 0, PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_VCONSTRAIN | PU_HCONSTRAIN); + } +} + +/* + * Returns the current X and Y coordinates of the mouse pointer. + * Parameters: + * x: Pointer to variable to store X coordinate. + * y: Pointer to variable to store Y coordinate. + */ +void API dw_pointer_query_pos(long *x, long *y) +{ + POINTL ptl; + + WinQueryPointerPos(HWND_DESKTOP, &ptl); + if(x && y) + { + *x = ptl.x; + *y = dw_screen_height() - ptl.y; + } +} + +/* + * Sets the X and Y coordinates of the mouse pointer. + * Parameters: + * x: X coordinate. + * y: Y coordinate. + */ +void API dw_pointer_set_pos(long x, long y) +{ + WinSetPointerPos(HWND_DESKTOP, x, dw_screen_height() - y); +} + + +/* + * Create a container object to be packed. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HWND API dw_container_new(ULONG id, int multi) +{ + WindowData *blah = calloc(1, sizeof(WindowData)); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_CONTAINER, + NULL, + WS_VISIBLE | CCS_READONLY | + (multi ? CCS_EXTENDSEL : CCS_SINGLESEL) | + CCS_AUTOPOSITION, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id ? id : _GlobalID(), + NULL, + NULL); + blah->oldproc = WinSubclassWindow(tmp, _TreeProc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_data(tmp, "_dw_container", (void *)1); + return tmp; +} + +/* + * Create a tree object to be packed. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HWND API dw_tree_new(ULONG id) +{ + CNRINFO cnrinfo; + WindowData *blah = calloc(1, sizeof(WindowData)); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_CONTAINER, + NULL, + WS_VISIBLE | CCS_READONLY | + CCS_SINGLESEL | CCS_AUTOPOSITION, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id ? id : _GlobalID(), + NULL, + NULL); + + cnrinfo.flWindowAttr = CV_TREE | CA_TREELINE; + cnrinfo.slBitmapOrIcon.cx = 16; + cnrinfo.slBitmapOrIcon.cy = 16; + cnrinfo.cyLineSpacing = 0; + cnrinfo.cxTreeIndent = 16; + cnrinfo.cxTreeLine = 1; + + WinSendMsg(tmp, CM_SETCNRINFO, &cnrinfo, MPFROMLONG(CMA_FLWINDOWATTR | CMA_SLBITMAPORICON | + CMA_LINESPACING | CMA_CXTREEINDENT | CMA_CXTREELINE)); + blah->oldproc = WinSubclassWindow(tmp, _TreeProc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Create a new static text window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_text_new(char *text, ULONG id) +{ + WindowData *blah = calloc(sizeof(WindowData), 1); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_STATIC, + text, + WS_VISIBLE | SS_TEXT, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + blah->oldproc = WinSubclassWindow(tmp, _textproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); + return tmp; +} + +/* + * Create a new status text window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_status_text_new(char *text, ULONG id) +{ + WindowData *blah = calloc(sizeof(WindowData), 1); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_STATIC, + text, + WS_VISIBLE | SS_TEXT, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + blah->oldproc = WinSubclassWindow(tmp, _statusproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); + return tmp; +} + +#ifndef MLS_LIMITVSCROLL +#define MLS_LIMITVSCROLL 0x00000080L +#endif + +/* + * Create a new Multiline Editbox window (widget) to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_mle_new(ULONG id) +{ + WindowData *blah = calloc(1, sizeof(WindowData)); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_MLE, + "", + WS_VISIBLE | + MLS_BORDER | MLS_IGNORETAB | + MLS_VSCROLL | + MLS_LIMITVSCROLL, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + WinSendMsg(tmp, MLM_FORMAT, (MPARAM)MLFIE_NOTRANS, 0); + blah->oldproc = WinSubclassWindow(tmp, _mleproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Create a new Entryfield window (widget) to be packed. + * Parameters: + * text: The default text to be in the entryfield widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_entryfield_new(char *text, ULONG id) +{ + + WindowData *blah = calloc(1, sizeof(WindowData)); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_ENTRYFIELD, + text, + WS_VISIBLE | ES_MARGIN | + ES_AUTOSCROLL | WS_TABSTOP, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + blah->oldproc = WinSubclassWindow(tmp, _entryproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE); + return tmp; +} + +/* + * Create a new Entryfield (password) window (widget) to be packed. + * Parameters: + * text: The default text to be in the entryfield widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_entryfield_password_new(char *text, ULONG id) +{ + WindowData *blah = calloc(1, sizeof(WindowData)); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_ENTRYFIELD, + text, + WS_VISIBLE | ES_MARGIN | ES_UNREADABLE | + ES_AUTOSCROLL | WS_TABSTOP, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + blah->oldproc = WinSubclassWindow(tmp, _entryproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE); + return tmp; +} + +/* + * Create a new Combobox window (widget) to be packed. + * Parameters: + * text: The default text to be in the combpbox widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_combobox_new(char *text, ULONG id) +{ + WindowData *blah = calloc(1, sizeof(WindowData)); + HWND frame = dw_box_new(DW_HORZ, 0); + HWND tmp = WinCreateWindow(frame, + WC_COMBOBOX, + text, + WS_VISIBLE | CBS_DROPDOWN | WS_GROUP, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id ? id : _GlobalID(), + NULL, + NULL); + HENUM henum = WinBeginEnumWindows(tmp); + HWND child, last = NULLHANDLE; + + while((child = WinGetNextWindow(henum)) != NULLHANDLE) + { + WindowData *moreblah = calloc(1, sizeof(WindowData)); + moreblah->oldproc = WinSubclassWindow(child, _comboentryproc); + WinSetWindowPtr(child, QWP_USER, moreblah); + dw_window_set_color(child, DW_CLR_BLACK, DW_CLR_WHITE); + last = child; + } + WinEndEnumWindows(henum); + blah->oldproc = WinSubclassWindow(tmp, _comboproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE); + dw_window_set_data(tmp, "_dw_comboentry", (void *)last); + dw_window_set_data(tmp, "_dw_combo_box", (void *)frame); + WinSetOwner(tmp, frame); + return tmp; +} + +/* + * Create a new button window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_button_new(char *text, ULONG id) +{ + BubbleButton *bubble = calloc(sizeof(BubbleButton), 1); + + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_BUTTON, + text, + WS_VISIBLE, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + + bubble->id = id; + bubble->bubbletext[0] = '\0'; + bubble->pOldProc = WinSubclassWindow(tmp, _BtProc); + + WinSetWindowPtr(tmp, QWP_USER, bubble); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); + return tmp; +} + +/* Function: GenResIDStr +** Abstract: Generate string '#nnnn' for a given ID for using with Button +** controls +*/ + +void _GenResIDStr(CHAR *buff, ULONG ulID) +{ + char *str; + int slen = 0; + + *buff++ = '#'; + + str = buff; + + do + { + *str++ = (ulID % 10) + '0'; + ulID /= 10; + slen++; + } + while(ulID); + + *str-- = 0; + + for(; str > buff; str--, buff++) + { + *buff ^= *str; + *str ^= *buff; + *buff ^= *str; + } +} + + +/* + * Create a new bitmap button window (widget) to be packed. + * Parameters: + * text: Bubble help text to be displayed. + * id: An ID of a bitmap in the resource file. + */ +HWND API dw_bitmapbutton_new(char *text, ULONG id) +{ + char idbuf[256], *name = NULL; + HWND tmp; + BubbleButton *bubble = calloc(sizeof(BubbleButton), 1); + HPOINTER icon = WinLoadPointer(HWND_DESKTOP, 0L, id); + + if(!icon) + { + name = idbuf; + _GenResIDStr(idbuf, id); + } + + tmp = WinCreateWindow(HWND_OBJECT, + WC_BUTTON, + name, + WS_VISIBLE | BS_PUSHBUTTON | + BS_NOPOINTERFOCUS | BS_AUTOSIZE | + (icon ? 0 : BS_BITMAP), + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + + bubble->id = id; + strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1); + bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0'; + bubble->pOldProc = WinSubclassWindow(tmp, _BtProc); + + WinSetWindowPtr(tmp, QWP_USER, bubble); + + if(icon) + dw_window_set_data(tmp, "_dw_button_icon", (void *)icon); + dw_window_set_data(tmp, "_dw_bitmapbutton", (void *)1); + return tmp; +} + +/* + * Create a new bitmap button window (widget) to be packed from a file. + * Parameters: + * text: Bubble help text to be displayed. + * id: An ID to be used with dw_window_from_id() or 0L. + * filename: Name of the file, omit extention to have + * DW pick the appropriate file extension. + * (BMP on OS/2 or Windows, XPM on Unix) + */ +HWND API dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename) +{ + BubbleButton *bubble = calloc(sizeof(BubbleButton), 1); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_BUTTON, + "", + WS_VISIBLE | BS_PUSHBUTTON | + BS_AUTOSIZE | BS_NOPOINTERFOCUS, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + char *file = alloca(strlen(filename) + 5); + HPIXMAP pixmap = NULL, disabled = NULL; + HPOINTER icon = 0; + + if(file && (pixmap = calloc(1,sizeof(struct _hpixmap)))) + { + int z, j, lim, len; + LONG fore; + + strcpy(file, filename); + + /* check if we can read from this file (it exists and read permission) */ + if(access(file, 04) == 0) + { + len = strlen( file ); + if(len > 4) + { + if(stricmp(file + len - 4, ".ico") == 0) + icon = WinLoadFileIcon(file, FALSE); + else + _load_bitmap_file(file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height); + } + } + else + { + /* Try with .ico extension first...*/ + strcat(file, ".ico"); + if(access(file, 04) == 0) + icon = WinLoadFileIcon(file, FALSE); + else + { + strcpy(file, filename); + strcat(file, ".bmp"); + if(access(file, 04) == 0) + _load_bitmap_file(file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height); + } + } + + if(icon) + { + free(pixmap); + pixmap = NULL; + } + 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; + } + } + + bubble->id = id; + strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1); + bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0'; + bubble->pOldProc = WinSubclassWindow(tmp, _BtProc); + + WinSetWindowPtr(tmp, QWP_USER, bubble); + + if(icon) + dw_window_set_data(tmp, "_dw_button_icon", (void *)icon); + else + { + dw_window_set_data(tmp, "_dw_hpixmap", (void *)pixmap); + dw_window_set_data(tmp, "_dw_hpixmap_disabled", (void *)disabled); + } + dw_window_set_data(tmp, "_dw_bitmapbutton", (void *)1); + return tmp; +} + +/* + * Create a new bitmap button window (widget) to be packed from data. + * Parameters: + * text: Bubble help text to be displayed. + * id: An ID to be used with dw_window_from_id() or 0L. + * data: The contents of the image + * (BMP or ICO on OS/2 or Windows, XPM on Unix) + * len: length of str + */ +HWND API dw_bitmapbutton_new_from_data(char *text, unsigned long id, char *data, int len) +{ + FILE *fp; + BubbleButton *bubble = calloc(sizeof(BubbleButton), 1); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_BUTTON, + "", + WS_VISIBLE | BS_PUSHBUTTON | + BS_AUTOSIZE | BS_NOPOINTERFOCUS, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + char *file; + HPIXMAP pixmap = NULL, disabled = NULL; + HPOINTER icon = 0; + + if ( ( pixmap = calloc( 1, sizeof(struct _hpixmap) ) ) ) + { + int z, j, lim; + LONG fore; + file = tmpnam( NULL ); + if ( file != NULL ) + { + fp = fopen( file, "wb" ); + if ( fp != NULL ) + { + fwrite( data, 1, len, fp ); + fclose( fp ); + if ( len > 1 && data[0] == 'B' && data[1] == 'M' ) /* first 2 chars of data is BM, then its a BMP */ + { + _load_bitmap_file( file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height ); + } + else /* otherwise its assumed to be an ico */ + { + icon = WinLoadFileIcon(file, FALSE); + } + } + else + { + unlink( file ); + return 0; + } + unlink( file ); + } + + if ( icon ) + { + free(pixmap); + pixmap = NULL; + } + 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; + } + } + + bubble->id = id; + strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1); + bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0'; + bubble->pOldProc = WinSubclassWindow(tmp, _BtProc); + + WinSetWindowPtr(tmp, QWP_USER, bubble); + + if(icon) + dw_window_set_data(tmp, "_dw_button_icon", (void *)icon); + else + { + dw_window_set_data(tmp, "_dw_hpixmap", (void *)pixmap); + dw_window_set_data(tmp, "_dw_hpixmap_disabled", (void *)disabled); + } + dw_window_set_data(tmp, "_dw_bitmapbutton", (void *)1); + return tmp; +} + +/* + * Create a new spinbutton window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_spinbutton_new(char *text, ULONG id) +{ + WindowData *blah = calloc(sizeof(WindowData), 1); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_SPINBUTTON, + text, + WS_VISIBLE | SPBS_MASTER, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + HWND entry = _find_entryfield(tmp); + WinSendMsg(tmp, SPBM_SETLIMITS, MPFROMLONG(65536), MPFROMLONG(-65536)); + WinSendMsg(tmp, SPBM_SETCURRENTVALUE, MPFROMLONG(atoi(text)), 0L); + blah->oldproc = WinSubclassWindow(tmp, _entryproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + blah = calloc(sizeof(WindowData), 1); + blah->oldproc = WinSubclassWindow(entry, _spinentryproc); + WinSetWindowPtr(entry, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(entry, DW_CLR_BLACK, DW_CLR_WHITE); + dw_window_set_data(tmp, "_dw_buddy", (void *)entry); + return tmp; +} + +/* + * Create a new radiobutton window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_radiobutton_new(char *text, ULONG id) +{ + WindowData *blah = calloc(sizeof(WindowData), 1); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_BUTTON, + text, + WS_VISIBLE | + BS_AUTORADIOBUTTON, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + blah->oldproc = WinSubclassWindow(tmp, _entryproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); + return tmp; +} + + +/* + * Create a new slider window (widget) to be packed. + * Parameters: + * vertical: TRUE or FALSE if slider is vertical. + * increments: Number of increments available. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_slider_new(int vertical, int increments, ULONG id) +{ + WindowData *blah = calloc(1, sizeof(WindowData)); + SLDCDATA sldcData = { 0, 0, 0, 0, 0 }; + HWND tmp; + + sldcData.cbSize = sizeof(SLDCDATA); + sldcData.usScale1Increments = increments; + + tmp = WinCreateWindow(HWND_OBJECT, + WC_SLIDER, + "", + WS_VISIBLE | SLS_SNAPTOINCREMENT | + (vertical ? SLS_VERTICAL : SLS_HORIZONTAL), + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id ? id : _GlobalID(), + &sldcData, + NULL); + + blah->oldproc = WinSubclassWindow(tmp, _entryproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + return tmp; +} + +/* + * Create a new scrollbar window (widget) to be packed. + * Parameters: + * vertical: TRUE or FALSE if scrollbar is vertical. + * increments: Number of increments available. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_scrollbar_new(int vertical, ULONG id) +{ + return WinCreateWindow(HWND_OBJECT, + WC_SCROLLBAR, + "", + WS_VISIBLE | SBS_AUTOTRACK | + (vertical ? SBS_VERT : SBS_HORZ), + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id ? id : _GlobalID(), + NULL, + NULL); +} + +/* + * Create a new percent bar window (widget) to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_percent_new(ULONG id) +{ + WindowData *blah = calloc(1, sizeof(WindowData)); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_SLIDER, + "", + WS_VISIBLE | SLS_READONLY + | SLS_RIBBONSTRIP, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id ? id : _GlobalID(), + NULL, + NULL); + blah->oldproc = WinSubclassWindow(tmp, _percentproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_disable(tmp); + return tmp; +} + +/* + * Create a new checkbox window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_checkbox_new(char *text, ULONG id) +{ + BubbleButton *bubble = calloc(sizeof(BubbleButton), 1); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_BUTTON, + text, + WS_VISIBLE | BS_AUTOCHECKBOX, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + bubble->id = id; + bubble->bubbletext[0] = '\0'; + bubble->pOldProc = WinSubclassWindow(tmp, _BtProc); + WinSetWindowPtr(tmp, QWP_USER, bubble); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); + return tmp; +} + +/* + * Create a new listbox window (widget) to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id() or 0L. + * multi: Multiple select TRUE or FALSE. + */ +HWND API dw_listbox_new(ULONG id, int multi) +{ + WindowData *blah = calloc(sizeof(WindowData), 1); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_LISTBOX, + NULL, + WS_VISIBLE | LS_NOADJUSTPOS | + (multi ? LS_MULTIPLESEL : 0), + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id ? id : _GlobalID(), + NULL, + NULL); + blah->oldproc = WinSubclassWindow(tmp, _entryproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE); + return tmp; +} + +/* + * Sets the icon used for a given window. + * Parameters: + * handle: Handle to the window. + * id: An ID to be used to specify the icon. + */ +void API dw_window_set_icon(HWND handle, HICN icon) +{ + HPOINTER hptr = icon < 65536 ? WinLoadPointer(HWND_DESKTOP,NULLHANDLE,icon) : (HPOINTER)icon; + WinSendMsg(handle, WM_SETICON, (MPARAM)hptr, 0); +} + +/* 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) +{ + HFILE BitmapFileHandle = NULLHANDLE; /* handle for the file */ + ULONG OpenAction = 0; + PBYTE BitmapFileBegin; /* pointer to the first byte of bitmap data */ + FILESTATUS BitmapStatus; + ULONG cbRead; + PBITMAPFILEHEADER2 pBitmapFileHeader; + PBITMAPINFOHEADER2 pBitmapInfoHeader; + ULONG ScanLines, ulFlags; + HPS hps1; + HDC hdc1; + SIZEL sizl = { 0, 0 }; + + /* open bitmap file */ + DosOpen(file, &BitmapFileHandle, &OpenAction, 0L, + FILE_ARCHIVED | FILE_NORMAL | FILE_READONLY, + OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, + OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY | + OPEN_FLAGS_NOINHERIT, 0L); + + if(!BitmapFileHandle) + return 0; + + /* find out how big the file is */ + DosQueryFileInfo(BitmapFileHandle, 1, &BitmapStatus, + sizeof(BitmapStatus)); + + /* allocate memory to load the bitmap */ + DosAllocMem((PPVOID)&BitmapFileBegin, (ULONG)BitmapStatus.cbFile, + PAG_READ | PAG_WRITE | PAG_COMMIT); + + /* read bitmap file into memory buffer */ + DosRead(BitmapFileHandle, (PVOID)BitmapFileBegin, + BitmapStatus.cbFile, &cbRead); + + /* access first bytes as bitmap header */ + pBitmapFileHeader = (PBITMAPFILEHEADER2)BitmapFileBegin; + + /* check if it's a valid bitmap data file */ + if((pBitmapFileHeader->usType != BFT_BITMAPARRAY) && + (pBitmapFileHeader->usType != BFT_BMAP)) + { + /* free memory of bitmap file buffer */ + DosFreeMem(BitmapFileBegin); + /* close the bitmap file */ + DosClose(BitmapFileHandle); + return 0; + } + + /* check if it's a file with multiple bitmaps */ + if(pBitmapFileHeader->usType == BFT_BITMAPARRAY) + { + /* we'll just use the first bitmap and ignore the others */ + pBitmapFileHeader = &(((PBITMAPARRAYFILEHEADER2)BitmapFileBegin)->bfh2); + } + + /* set pointer to bitmap information block */ + pBitmapInfoHeader = &pBitmapFileHeader->bmp2; + + /* find out if it's the new 2.0 format or the old format */ + /* and query number of lines */ + if(pBitmapInfoHeader->cbFix == sizeof(BITMAPINFOHEADER)) + { + *height = ScanLines = (ULONG)((PBITMAPINFOHEADER)pBitmapInfoHeader)->cy; + *width = (ULONG)((PBITMAPINFOHEADER)pBitmapInfoHeader)->cx; + } + else + { + *height = ScanLines = pBitmapInfoHeader->cy; + *width = pBitmapInfoHeader->cx; + } + + /* now we need a presentation space, get it from static control */ + hps1 = WinGetPS(handle); + + hdc1 = GpiQueryDevice(hps1); + ulFlags = GpiQueryPS(hps1, &sizl); + + *hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc1); + *hps = GpiCreatePS (dwhab, *hdc, &sizl, ulFlags | GPIA_ASSOC); + + /* create bitmap now using the parameters from the info block */ + *hbm = GpiCreateBitmap(*hps, pBitmapInfoHeader, 0L, NULL, NULL); + + /* select the new bitmap into presentation space */ + GpiSetBitmap(*hps, *hbm); + + /* now copy the bitmap data into the bitmap */ + GpiSetBitmapBits(*hps, 0L, ScanLines, + BitmapFileBegin + pBitmapFileHeader->offBits, + (PBITMAPINFO2)pBitmapInfoHeader); + + WinReleasePS(hps1); + + /* free memory of bitmap file buffer */ + DosFreeMem(BitmapFileBegin); + /* close the bitmap file */ + DosClose(BitmapFileHandle); + return 1; +} + +/* + * Sets the bitmap used for a given static window. + * Parameters: + * handle: Handle to the window. + * id: An ID to be used to specify the icon, + * (pass 0 if you use the filename param) + * filename: a path to a file (Bitmap on OS/2 or + * Windows and a pixmap on Unix, pass + * NULL if you use the id param) + */ +void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename) +{ + HBITMAP hbm; + HPS hps; + + /* Destroy any old bitmap data */ + _free_bitmap(handle); + + /* If id is non-zero use the resource */ + if ( id ) + { + hps = WinGetPS( handle ); + hbm = GpiLoadBitmap( hps, NULLHANDLE, id, 0, 0 ); + } + else if ( filename ) + { + HDC hdc; + unsigned long width, height; + char *file = alloca(strlen(filename) + 5); + + if(!file) + return; + + strcpy(file, filename); + + /* check if we can read from this file (it exists and read permission) */ + if(access(file, 04) != 0) + { + /* Try with .bmp extention */ + strcat(file, ".bmp"); + if(access(file, 04) != 0) + return; + } + + if(!_load_bitmap_file(file, handle, &hbm, &hdc, &hps, &width, &height)) + return; + + dw_window_set_data(handle, "_dw_hps", (void *)hps); + dw_window_set_data(handle, "_dw_hdc", (void *)hdc); + dw_window_set_data(handle, "_dw_width", (void *)width); + dw_window_set_data(handle, "_dw_height", (void *)height); + } + else + return; + + WinSetWindowBits(handle,QWL_STYLE,SS_BITMAP,SS_BITMAP | 0x7f); + WinSendMsg( handle, SM_SETHANDLE, MPFROMP(hbm), NULL ); + if ( id ) + WinReleasePS(hps); + dw_window_set_data(handle, "_dw_bitmap", (void *)hbm); +} + +/* + * Sets the bitmap used for a given static window. + * Parameters: + * handle: Handle to the window. + * id: An ID to be used to specify the icon, + * (pass 0 if you use the filename param) + * filename: a path to a file (Bitmap on OS/2 or + * Windows and a pixmap on Unix, pass + * NULL if you use the id param) + */ +void API dw_window_set_bitmap_from_data(HWND handle, unsigned long id, char *data, int len) +{ + HBITMAP hbm; + HPS hps; + HDC hdc; + unsigned long width, height; + char *file; + FILE *fp; + + /* Destroy any old bitmap data */ + _free_bitmap(handle); + + /* If id is non-zero use the resource */ + if ( id ) + { + hps = WinGetPS( handle ); + hbm = GpiLoadBitmap( hps, NULLHANDLE, id, 0, 0 ); + } + else if ( data ) + { + file = tmpnam( NULL ); + if ( file != NULL ) + { + fp = fopen( file, "wb" ); + if ( fp != NULL ) + { + fwrite( data, 1, len, fp ); + fclose( fp ); + if ( len > 1 && data[0] == 'B' && data[1] == 'M' ) /* first 2 chars of data is BM, then its a BMP */ + _load_bitmap_file(file, handle, &hbm, &hdc, &hps, &width, &height); + else /* otherwise its assumed to be an ico */ + { + /* con't use ICO ? */ + unlink( file ); + return; + } + } + else + { + unlink( file ); + return; + } + unlink( file ); + } + + dw_window_set_data(handle, "_dw_hps", (void *)hps); + dw_window_set_data(handle, "_dw_hdc", (void *)hdc); + dw_window_set_data(handle, "_dw_width", (void *)width); + dw_window_set_data(handle, "_dw_height", (void *)height); + } + else + return; + + WinSetWindowBits(handle,QWL_STYLE,SS_BITMAP,SS_BITMAP | 0x7f); + WinSendMsg( handle, SM_SETHANDLE, MPFROMP(hbm), NULL ); + if ( id ) + WinReleasePS(hps); + dw_window_set_data(handle, "_dw_bitmap", (void *)hbm); +} + +/* + * Sets the text used for a given window. + * Parameters: + * handle: Handle to the window. + * text: The text associsated with a given window. + */ +void API dw_window_set_text(HWND handle, char *text) +{ + HWND entryfield = (HWND)dw_window_get_data(handle, "_dw_buddy"); + WinSetWindowText(entryfield ? entryfield : handle, text); +} + +/* + * Gets the text used for a given window. + * Parameters: + * handle: Handle to the window. + * Returns: + * text: The text associsated with a given window. + */ +char * API dw_window_get_text(HWND handle) +{ + HWND entryfield = (HWND)dw_window_get_data(handle, "_dw_buddy"); + int len = WinQueryWindowTextLength(entryfield ? entryfield : handle); + char *tempbuf = calloc(1, len + 2); + + WinQueryWindowText(entryfield ? entryfield : handle, len + 1, tempbuf); + + return tempbuf; +} + +/* + * Disables given window (widget). + * Parameters: + * handle: Handle to the window. + */ +void API dw_window_disable(HWND handle) +{ + char tmpbuf[100]; + + if(handle < 65536) + { + char buffer[30]; + HMENUI mymenu; + + sprintf(buffer, "_dw_id%ld", handle); + mymenu = (HMENUI)dw_window_get_data(hwndApp, buffer); + + if(mymenu && WinIsWindow(dwhab, mymenu)) + dw_menu_item_set_state(mymenu, handle, DW_MIS_DISABLED); + return; + } + + if(dw_window_get_data(handle, "_dw_disabled")) + return; + + WinQueryClassName(handle, 99, tmpbuf); + dw_window_set_data(handle, "_dw_disabled", (void *)1); + + if(tmpbuf[0] == '#') + { + int val = atoi(&tmpbuf[1]); + HWND hwnd; + + switch(val) + { + case 2: + case 6: + case 10: + case 32: + case 7: + hwnd = _find_entryfield(handle); + _dw_window_set_color(hwnd ? hwnd : handle, DW_CLR_BLACK, DW_CLR_PALEGRAY); + dw_signal_connect(hwnd ? hwnd : handle, DW_SIGNAL_KEY_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100); + if(val == 2) + dw_signal_connect(handle, DW_SIGNAL_BUTTON_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100); + if(hwnd) + dw_window_set_data(hwnd, "_dw_disabled", (void *)1); + return; + case 3: + if(dw_window_get_data(handle, "_dw_bitmapbutton") && !dw_window_get_data(handle, "_dw_hpixmap")) + WinEnableWindow(handle, FALSE); + else if(dw_window_get_data(handle, "_dw_bitmapbutton") && dw_window_get_data(handle, "_dw_hpixmap_disabled")) + WinInvalidateRect(handle, NULL, FALSE); + else + _dw_window_set_color(handle, DW_CLR_DARKGRAY, DW_CLR_PALEGRAY); + dw_signal_connect(handle, DW_SIGNAL_KEY_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100); + dw_signal_connect(handle, DW_SIGNAL_BUTTON_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100); + return; + } + } + WinEnableWindow(handle, FALSE); +} + +/* + * Enables given window (widget). + * Parameters: + * handle: Handle to the window. + */ +void API dw_window_enable(HWND handle) +{ + ULONG fore = (ULONG)dw_window_get_data(handle, "_dw_fore"); + ULONG back = (ULONG)dw_window_get_data(handle, "_dw_back"); + HWND hwnd = _find_entryfield(handle); + + if(handle < 65536) + { + char buffer[30]; + HMENUI mymenu; + + sprintf(buffer, "_dw_id%ld", handle); + mymenu = (HMENUI)dw_window_get_data(hwndApp, buffer); + + if(mymenu && WinIsWindow(dwhab, mymenu)) + dw_menu_item_set_state(mymenu, handle, DW_MIS_ENABLED); + return; + } + + dw_window_set_data(handle, "_dw_disabled", 0); + if(hwnd) + dw_window_set_data(hwnd, "_dw_disabled", 0); + if(fore && back) + _dw_window_set_color(hwnd ? hwnd : handle, fore-1, back-1); + dw_signal_disconnect_by_data(handle, (void *)100); + WinEnableWindow(handle, TRUE); + if(dw_window_get_data(handle, "_dw_bitmapbutton") && dw_window_get_data(handle, "_dw_hpixmap_disabled")) + WinInvalidateRect(handle, NULL, FALSE); +} + +/* + * Gets the child window handle with specified ID. + * Parameters: + * handle: Handle to the parent window. + * id: Integer ID of the child. + */ +HWND API dw_window_from_id(HWND handle, int id) +{ + HENUM henum; + HWND child; + char tmpbuf[100]; + + henum = WinBeginEnumWindows(handle); + while((child = WinGetNextWindow(henum)) != NULLHANDLE) + { + int windowid = WinQueryWindowUShort(child, QWS_ID); + HWND found; + + WinQueryClassName(child, 99, tmpbuf); + + /* If the child is a box (frame) then recurse into it */ + if(strncmp(tmpbuf, "#1", 3)==0) + if((found = dw_window_from_id(child, id)) != NULLHANDLE) + return found; + + if(windowid && windowid == id) + { + WinEndEnumWindows(henum); + return child; + } + } + WinEndEnumWindows(henum); + return NULLHANDLE; +} + +/* Internal box packing function called by the other 3 functions */ +void _dw_box_pack(HWND box, HWND item, int index, int width, int height, int hsize, int vsize, int pad, char *funcname) +{ + Box *thisbox; + + /* + * If you try and pack an item into itself VERY bad things can happen; like at least an + * infinite loop on GTK! Lets be safe! + */ + if(box == item) + { + dw_messagebox(funcname, DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!"); + return; + } + + if(WinWindowFromID(box, FID_CLIENT)) + { + HWND intbox = (HWND)dw_window_get_data(box, "_dw_box"); + if(intbox) + { + box = intbox; + } + else + { + box = WinWindowFromID(box, FID_CLIENT); + hsize = vsize = TRUE; + } + } + + thisbox = WinQueryWindowPtr(box, QWP_USER); + + if(thisbox) + { + int z, x = 0; + Item *tmpitem, *thisitem = thisbox->items; + char tmpbuf[100]; + HWND frame = (HWND)dw_window_get_data(item, "_dw_combo_box"); + + /* Do some sanity bounds checking */ + if(index < 0) + index = 0; + if(index > thisbox->count) + index = thisbox->count; + + tmpitem = malloc(sizeof(Item)*(thisbox->count+1)); + + for(z=0;z<thisbox->count;z++) + { + if(z == index) + x++; + tmpitem[x] = thisitem[z]; + x++; + } + + + WinQueryClassName(item, 99, tmpbuf); + + if(vsize && !height) + height = 1; + if(hsize && !width) + width = 1; + + if(strncmp(tmpbuf, "#1", 3)==0) + tmpitem[index].type = TYPEBOX; + else + { + if ( width == 0 && hsize == FALSE ) + dw_messagebox(funcname, DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item); + if ( height == 0 && vsize == FALSE ) + dw_messagebox(funcname, DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item); + + tmpitem[index].type = TYPEITEM; + } + + tmpitem[index].hwnd = item; + tmpitem[index].origwidth = tmpitem[index].width = width; + tmpitem[index].origheight = tmpitem[index].height = height; + tmpitem[index].pad = pad; + if(hsize) + tmpitem[index].hsize = SIZEEXPAND; + else + tmpitem[index].hsize = SIZESTATIC; + + if(vsize) + tmpitem[index].vsize = SIZEEXPAND; + else + tmpitem[index].vsize = SIZESTATIC; + + thisbox->items = tmpitem; + + if(thisbox->count) + free(thisitem); + + thisbox->count++; + + WinQueryClassName(item, 99, tmpbuf); + /* Don't set the ownership if it's an entryfield or spinbutton */ + if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 4)!=0 && strncmp(tmpbuf, "#2", 3)!=0) + WinSetOwner(item, box); + WinSetParent(frame ? frame : item, box, FALSE); + } +} + +/* + * Pack windows (widgets) into a box at an arbitrary location. + * Parameters: + * box: Window handle of the box to be packed into. + * item: Window handle of the item to be back. + * index: 0 based index of packed items. + * width: Width in pixels of the item or -1 to be self determined. + * height: Height in pixels of the item or -1 to be self determined. + * hsize: TRUE if the window (widget) should expand horizontally to fill space given. + * vsize: TRUE if the window (widget) should expand vertically to fill space given. + * pad: Number of pixels of padding around the item. + */ +void API dw_box_pack_at_index(HWND box, HWND item, int index, int width, int height, int hsize, int vsize, int pad) +{ + _dw_box_pack(box, item, index, width, height, hsize, vsize, pad, "dw_box_pack_at_index()"); +} + +/* + * Pack windows (widgets) into a box from the start (or top). + * Parameters: + * box: Window handle of the box to be packed into. + * item: Window handle of the item to be back. + * width: Width in pixels of the item or -1 to be self determined. + * height: Height in pixels of the item or -1 to be self determined. + * hsize: TRUE if the window (widget) should expand horizontally to fill space given. + * vsize: TRUE if the window (widget) should expand vertically to fill space given. + * pad: Number of pixels of padding around the item. + */ +void API dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) +{ + /* 65536 is the table limit on GTK... + * seems like a high enough value we will never hit it here either. + */ + _dw_box_pack(box, item, 65536, width, height, hsize, vsize, pad, "dw_box_pack_start()"); +} + +/* + * Pack windows (widgets) into a box from the end (or bottom). + * Parameters: + * box: Window handle of the box to be packed into. + * item: Window handle of the item to be back. + * width: Width in pixels of the item or -1 to be self determined. + * height: Height in pixels of the item or -1 to be self determined. + * hsize: TRUE if the window (widget) should expand horizontally to fill space given. + * vsize: TRUE if the window (widget) should expand vertically to fill space given. + * pad: Number of pixels of padding around the item. + */ +void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) +{ + _dw_box_pack(box, item, 0, width, height, hsize, vsize, pad, "dw_box_pack_end()"); +} + +/* + * Sets the size of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * width: New width in pixels. + * height: New height in pixels. + */ +void API dw_window_set_size(HWND handle, ULONG width, ULONG height) +{ + WinSetWindowPos(handle, NULLHANDLE, 0, 0, width, height, SWP_SHOW | SWP_SIZE); +} + +/* + * Returns the width of the screen. + */ +int API dw_screen_width(void) +{ + return WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN); +} + +/* + * Returns the height of the screen. + */ +int API dw_screen_height(void) +{ + return WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN); +} + +/* This should return the current color depth */ +unsigned long API dw_color_depth_get(void) +{ + HDC hdc = WinOpenWindowDC(HWND_DESKTOP); + long colors; + + DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1, &colors); + DevCloseDC(hdc); + return colors; +} + + +/* + * Sets the position of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * x: X location from the bottom left. + * y: Y location from the bottom left. + */ +void API dw_window_set_pos(HWND handle, LONG x, LONG y) +{ + int myy = _get_frame_height(handle) - (y + _get_height(handle)); + + WinSetWindowPos(handle, NULLHANDLE, x, myy, 0, 0, SWP_MOVE); +} + +/* + * Sets the position and size of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * x: X location from the bottom left. + * y: Y location from the bottom left. + * width: Width of the widget. + * height: Height of the widget. + */ +void API dw_window_set_pos_size(HWND handle, LONG x, LONG y, ULONG width, ULONG height) +{ + int myy = _get_frame_height(handle) - (y + height); + + WinSetWindowPos(handle, NULLHANDLE, x, myy, width, height, SWP_MOVE | SWP_SIZE | SWP_SHOW); +} + +/* + * Gets the position and size of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * x: X location from the bottom left. + * y: Y location from the bottom left. + * width: Width of the widget. + * height: Height of the widget. + */ +void API dw_window_get_pos_size(HWND handle, LONG *x, LONG *y, ULONG *width, ULONG *height) +{ + SWP swp; + WinQueryWindowPos(handle, &swp); + if(x) + *x = swp.x; + if(y) + *y = _get_frame_height(handle) - (swp.y + swp.cy); + if(width) + *width = swp.cx; + if(height) + *height = swp.cy; +} + +/* + * Sets the style of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * width: New width in pixels. + * height: New height in pixels. + */ +void API dw_window_set_style(HWND handle, ULONG style, ULONG mask) +{ + if(handle < 65536) + { + char buffer[30]; + HMENUI mymenu; + + sprintf(buffer, "_dw_id%ld", handle); + mymenu = (HMENUI)dw_window_get_data(hwndApp, buffer); + + if(mymenu && WinIsWindow(dwhab, mymenu)) + dw_menu_item_set_state(mymenu, handle, style & mask); + } + else + WinSetWindowBits(handle, QWL_STYLE, style, mask); +} + +/* + * Adds a new page to specified notebook. + * Parameters: + * handle: Window (widget) handle. + * flags: Any additional page creation flags. + * front: If TRUE page is added at the beginning. + */ +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)); +} + +/* + * Remove a page from a notebook. + * Parameters: + * handle: Handle to the notebook widget. + * pageid: ID of the page to be destroyed. + */ +void API dw_notebook_page_destroy(HWND handle, unsigned int pageid) +{ + HWND pagehwnd = (HWND)WinSendMsg(handle, BKM_QUERYPAGEWINDOWHWND, + MPFROMLONG(pageid), 0L); + WinSendMsg(handle, BKM_DELETEPAGE, + MPFROMLONG(pageid), (MPARAM)BKA_SINGLE); + if(pagehwnd) + dw_window_destroy(pagehwnd); +} + +/* + * Queries the currently visible page ID. + * Parameters: + * handle: Handle to the notebook widget. + */ +unsigned long API dw_notebook_page_get(HWND handle) +{ + return (unsigned long)WinSendMsg(handle, BKM_QUERYPAGEID,0L, MPFROM2SHORT(BKA_TOP, BKA_MAJOR)); +} + +/* + * Sets the currently visibale page ID. + * Parameters: + * handle: Handle to the notebook widget. + * pageid: ID of the page to be made visible. + */ +void API dw_notebook_page_set(HWND handle, unsigned int pageid) +{ + WinSendMsg(handle, BKM_TURNTOPAGE, MPFROMLONG(pageid), 0L); +} + +/* + * Sets the text on the specified notebook tab. + * Parameters: + * handle: Notebook handle. + * pageid: Page ID of the tab to set. + * text: Pointer to the text to set. + */ +void API dw_notebook_page_set_text(HWND handle, ULONG pageid, char *text) +{ + WinSendMsg(handle, BKM_SETTABTEXT, + MPFROMLONG(pageid), MPFROMP(text)); +} + +/* + * Sets the text on the specified notebook tab status area. + * Parameters: + * handle: Notebook handle. + * pageid: Page ID of the tab to set. + * text: Pointer to the text to set. + */ +void API dw_notebook_page_set_status_text(HWND handle, ULONG pageid, char *text) +{ + WinSendMsg(handle, BKM_SETSTATUSLINETEXT, + MPFROMLONG(pageid), MPFROMP(text)); +} + +/* + * Packs the specified box into the notebook page. + * Parameters: + * handle: Handle to the notebook to be packed. + * pageid: Page ID in the notebook which is being packed. + * page: Box handle to be packed. + */ +void API dw_notebook_pack(HWND handle, ULONG pageid, HWND page) +{ + HWND tmpbox = dw_box_new(DW_VERT, 0); + + dw_box_pack_start(tmpbox, page, 0, 0, TRUE, TRUE, 0); + WinSubclassWindow(tmpbox, _wndproc); + WinSendMsg(handle, BKM_SETPAGEWINDOWHWND, + MPFROMLONG(pageid), MPFROMHWND(tmpbox)); +} + +/* + * Appends the specified text to the listbox's (or combobox) entry list. + * Parameters: + * handle: Handle to the listbox to be appended to. + * text: Text to append into listbox. + */ +void API dw_listbox_append(HWND handle, char *text) +{ + WinSendMsg(handle, + LM_INSERTITEM, + MPFROMSHORT(LIT_END), + MPFROMP(text)); +} + +/* + * Inserts the specified text into the listbox's (or combobox) entry list. + * Parameters: + * handle: Handle to the listbox to be inserted into. + * text: Text to insert into listbox. + * pos: 0-based position to insert text + */ +void API dw_listbox_insert(HWND handle, char *text, int pos) +{ + WinSendMsg(handle, + LM_INSERTITEM, + MPFROMSHORT(pos), + MPFROMP(text)); +} + +/* + * Appends the specified text items to the listbox's (or combobox) entry list. + * Parameters: + * handle: Handle to the listbox to be appended to. + * text: Text strings to append into listbox. + * count: Number of text strings to append + */ +void API dw_listbox_list_append(HWND handle, char **text, int count) +{ + int i; + for(i=0;i<count;i++) + WinSendMsg(handle, + LM_INSERTITEM, + MPFROMSHORT(LIT_END), + MPFROMP(text[i])); +} + +/* + * Clears the listbox's (or combobox) list of all entries. + * Parameters: + * handle: Handle to the listbox to be cleared. + */ +void API dw_listbox_clear(HWND handle) +{ + WinSendMsg(handle, + LM_DELETEALL, 0L, 0L); +} + +/* + * Returns the listbox's item count. + * Parameters: + * handle: Handle to the listbox to be cleared. + */ +int API dw_listbox_count(HWND handle) +{ + return (int)WinSendMsg(handle, + LM_QUERYITEMCOUNT,0L, 0L); +} + +/* + * Sets the topmost item in the viewport. + * Parameters: + * handle: Handle to the listbox to be cleared. + * top: Index to the top item. + */ +void API dw_listbox_set_top(HWND handle, int top) +{ + WinSendMsg(handle, + LM_SETTOPINDEX, + MPFROMSHORT(top), + 0L); +} + +/* + * Copies the given index item's text into buffer. + * Parameters: + * handle: Handle to the listbox to be queried. + * index: Index into the list to be queried. + * buffer: Buffer where text will be copied. + * length: Length of the buffer (including NULL). + */ +void API dw_listbox_get_text(HWND handle, unsigned int index, char *buffer, unsigned int length) +{ + WinSendMsg(handle, LM_QUERYITEMTEXT, MPFROM2SHORT(index, length), (MPARAM)buffer); +} + +/* + * Sets the text of a given listbox entry. + * Parameters: + * handle: Handle to the listbox to be queried. + * index: Index into the list to be queried. + * buffer: Buffer where text will be copied. + */ +void API dw_listbox_set_text(HWND handle, unsigned int index, char *buffer) +{ + WinSendMsg(handle, LM_SETITEMTEXT, MPFROMSHORT(index), (MPARAM)buffer); +} + +/* + * Returns the index to the item in the list currently selected. + * Parameters: + * handle: Handle to the listbox to be queried. + */ +int API dw_listbox_selected(HWND handle) +{ + return (unsigned int)WinSendMsg(handle, + LM_QUERYSELECTION, + MPFROMSHORT(LIT_CURSOR), + 0); +} + +/* + * Returns the index to the current selected item or -1 when done. + * Parameters: + * handle: Handle to the listbox to be queried. + * where: Either the previous return or -1 to restart. + */ +int API dw_listbox_selected_multi(HWND handle, int where) +{ + int place = where; + + if(where == -1) + place = LIT_FIRST; + + place = (int)WinSendMsg(handle, + LM_QUERYSELECTION, + MPFROMSHORT(place),0L); + if(place == LIT_NONE) + return -1; + return place; +} + +/* + * Sets the selection state of a given index. + * Parameters: + * handle: Handle to the listbox to be set. + * index: Item index. + * state: TRUE if selected FALSE if unselected. + */ +void API dw_listbox_select(HWND handle, int index, int state) +{ + char tmpbuf[100]; + + WinSendMsg(handle, LM_SELECTITEM, MPFROMSHORT(index), (MPARAM)state); + + WinQueryClassName(handle, 99, tmpbuf); + + /* If we are setting a combobox call the event handler manually */ + if(strncmp(tmpbuf, "#6", 3)==0) + _run_event(handle, WM_CONTROL, MPFROM2SHORT(0, LN_SELECT), (MPARAM)handle); +} + +/* + * Deletes the item with given index from the list. + * Parameters: + * handle: Handle to the listbox to be set. + * index: Item index. + */ +void API dw_listbox_delete(HWND handle, int index) +{ + WinSendMsg(handle, LM_DELETEITEM, MPFROMSHORT(index), 0); +} + +/* + * Adds text to an MLE box and returns the current point. + * Parameters: + * handle: Handle to the MLE to be queried. + * buffer: Text buffer to be imported. + * startpoint: Point to start entering text. + */ +unsigned int API dw_mle_import(HWND handle, char *buffer, int startpoint) +{ + long point = startpoint < 0 ? 0 : startpoint; + PBYTE mlebuf; + + /* Work around 64K limit */ + if(!DosAllocMem((PPVOID) &mlebuf, 65536, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE)) + { + int amount, len = strlen(buffer), written = 0; + + while(written < len) + { + int z, x = 0; + + if((len - written) > 65535) + amount = 65535; + else + amount = len - written; + + /* Remove Carriage Returns \r */ + for(z=0;z<amount;z++) + { + if(buffer[z] != '\r') + { + mlebuf[x] = buffer[z]; + x++; + } + } + + if(point < 0) + point = 0; + WinSendMsg(handle, MLM_SETIMPORTEXPORT, MPFROMP(mlebuf), MPFROMLONG(x)); + WinSendMsg(handle, MLM_IMPORT, MPFROMP(&point), MPFROMLONG(x)); + + written += amount; + } + DosFreeMem(mlebuf); + } + return point; +} + +/* + * Grabs text from an MLE box. + * Parameters: + * handle: Handle to the MLE to be queried. + * buffer: Text buffer to be exported. + * startpoint: Point to start grabbing text. + * length: Amount of text to be grabbed. + */ +void API dw_mle_export(HWND handle, char *buffer, int startpoint, int length) +{ + PBYTE mlebuf; + + /* Work around 64K limit */ + if(!DosAllocMem((PPVOID) &mlebuf, 65535, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE)) + { + int amount, copied, written = 0; + + while(written < length) + { + if((length - written) > 65535) + amount = 65535; + else + amount = length - written; + + WinSendMsg(handle, MLM_SETIMPORTEXPORT, MPFROMP(mlebuf), MPFROMLONG(amount)); + copied = (int)WinSendMsg(handle, MLM_EXPORT, MPFROMP(&startpoint), MPFROMLONG(&amount)); + + if(copied) + { + memcpy(&buffer[written], mlebuf, copied); + + written += copied; + } + else + break; + } + DosFreeMem(mlebuf); + } +} + +/* + * Obtains information about an MLE box. + * Parameters: + * handle: Handle to the MLE to be queried. + * bytes: A pointer to a variable to return the total bytes. + * lines: A pointer to a variable to return the number of lines. + */ +void API dw_mle_get_size(HWND handle, unsigned long *bytes, unsigned long *lines) +{ + if(bytes) + *bytes = (unsigned long)WinSendMsg(handle, MLM_QUERYTEXTLENGTH, 0, 0); + if(lines) + *lines = (unsigned long)WinSendMsg(handle, MLM_QUERYLINECOUNT, 0, 0); +} + +/* + * Deletes text from an MLE box. + * Parameters: + * handle: Handle to the MLE to be deleted from. + * startpoint: Point to start deleting text. + * length: Amount of text to be deleted. + */ +void API dw_mle_delete(HWND handle, int startpoint, int length) +{ + WinSendMsg(handle, MLM_DELETE, MPFROMLONG(startpoint), MPFROMLONG(length)); +} + +/* + * Clears all text from an MLE box. + * Parameters: + * handle: Handle to the MLE to be cleared. + */ +void API dw_mle_clear(HWND handle) +{ + unsigned long bytes; + + dw_mle_get_size(handle, &bytes, NULL); + + WinSendMsg(handle, MLM_DELETE, MPFROMLONG(0), MPFROMLONG(bytes)); +} + +/* + * Sets the visible line of an MLE box. + * Parameters: + * handle: Handle to the MLE to be positioned. + * line: Line to be visible. + */ +void API dw_mle_set_visible(HWND handle, int line) +{ + int tmppnt = (int)WinSendMsg(handle, MLM_CHARFROMLINE, MPFROMLONG(line), 0); + WinSendMsg(handle, MLM_SETSEL, MPFROMLONG(tmppnt), MPFROMLONG(tmppnt)); +} + +/* + * Sets the editablity of an MLE box. + * Parameters: + * handle: Handle to the MLE. + * state: TRUE if it can be edited, FALSE for readonly. + */ +void API dw_mle_set_editable(HWND handle, int state) +{ + WinSendMsg(handle, MLM_SETREADONLY, MPFROMLONG(state ? FALSE : TRUE), 0); +} + +/* + * Sets the word wrap state of an MLE box. + * Parameters: + * handle: Handle to the MLE. + * state: TRUE if it wraps, FALSE if it doesn't. + */ +void API dw_mle_set_word_wrap(HWND handle, int state) +{ + WinSendMsg(handle, MLM_SETWRAP, MPFROMLONG(state), 0); +} + +/* + * Sets the current cursor position of an MLE box. + * Parameters: + * handle: Handle to the MLE to be positioned. + * point: Point to position cursor. + */ +void API dw_mle_set_cursor(HWND handle, int point) +{ + WinSendMsg(handle, MLM_SETSEL, MPFROMLONG(point), MPFROMLONG(point)); +} + +/* + * Finds text in an MLE box. + * Parameters: + * handle: Handle to the MLE to be cleared. + * text: Text to search for. + * point: Start point of search. + * flags: Search specific flags. + */ +int API dw_mle_search(HWND handle, char *text, int point, unsigned long flags) +{ + MLE_SEARCHDATA msd; + + /* This code breaks with structure packing set to 1 (/Sp1 in VAC) + * if this is needed we need to add a pragma here. + */ + msd.cb = sizeof(msd); + msd.pchFind = text; + msd.pchReplace = NULL; + msd.cchFind = strlen(text); + msd.cchReplace = 0; + msd.iptStart = point; + msd.iptStop = -1; + + if(WinSendMsg(handle, MLM_SEARCH, MPFROMLONG(MLFSEARCH_SELECTMATCH | flags), (MPARAM)&msd)) + return (int)WinSendMsg(handle, MLM_QUERYSEL,(MPARAM)MLFQS_MAXSEL, 0); + return 0; +} + +/* + * Stops redrawing of an MLE box. + * Parameters: + * handle: Handle to the MLE to freeze. + */ +void API dw_mle_freeze(HWND handle) +{ + WinSendMsg(handle, MLM_DISABLEREFRESH, 0, 0); +} + +/* + * Resumes redrawing of an MLE box. + * Parameters: + * handle: Handle to the MLE to thaw. + */ +void API dw_mle_thaw(HWND handle) +{ + WinSendMsg(handle, MLM_ENABLEREFRESH, 0, 0); +} + +/* Internal version that can be called from _percentthread */ +void _dw_percent_set_pos(HWND handle, unsigned int position) +{ + int range = _dw_percent_get_range(handle); + + if(range) + { + int mypos = (((float)position)/100)*range; + + if(mypos >= range) + mypos = range - 1; + + _dw_int_set(handle, mypos); + WinSendMsg(handle, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), (MPARAM)mypos); + } +} + +/* Move the percentage bar backwards to simulate indeterminate */ +void _percentthread(void *data) +{ + HWND percent = (HWND)data; + + if(percent) + { + HAB thishab = WinInitialize(0); + HMQ thishmq = WinCreateMsgQueue(dwhab, 0); + + int pos = 100; + + do + { + pos--; + if(pos < 1) + pos = 100; + _dw_percent_set_pos(percent, pos); + DosSleep(100); + } + while(dw_window_get_data(percent, "_dw_ind")); + + WinDestroyMsgQueue(thishmq); + WinTerminate(thishab); + } +} + +/* + * Sets the percent bar position. + * Parameters: + * handle: Handle to the percent bar to be set. + * position: Position of the percent bar withing the range. + */ +void API dw_percent_set_pos(HWND handle, unsigned int position) +{ + /* OS/2 doesn't really support indeterminate... */ + if(position == DW_PERCENT_INDETERMINATE) + { + if(!dw_window_get_data(handle, "_dw_ind")) + { + /* So we fake it with a thread */ + dw_window_set_data(handle, "_dw_ind", (void *)1); + _beginthread(_percentthread, NULL, 100, (void *)handle); + } + } + else + { + /* Make sure we are no longer indeterminate */ + dw_window_set_data(handle, "_dw_ind", NULL); + /* Otherwise set the position as usual */ + _dw_percent_set_pos(handle, position); + } +} + +/* + * Returns the position of the slider. + * Parameters: + * handle: Handle to the slider to be queried. + */ +unsigned int API dw_slider_get_pos(HWND handle) +{ + return (unsigned int)WinSendMsg(handle, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0); +} + +/* + * Sets the slider position. + * Parameters: + * handle: Handle to the slider to be set. + * position: Position of the slider withing the range. + */ +void API dw_slider_set_pos(HWND handle, unsigned int position) +{ + dw_window_set_data(handle, "_dw_slider_value", (void *)position); + WinSendMsg(handle, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), (MPARAM)position); +} + +/* + * Returns the position of the scrollbar. + * Parameters: + * handle: Handle to the scrollbar to be queried. + */ +unsigned int API dw_scrollbar_get_pos(HWND handle) +{ + return (unsigned int)WinSendMsg(handle, SBM_QUERYPOS, 0, 0); +} + +/* + * Sets the scrollbar position. + * Parameters: + * handle: Handle to the scrollbar to be set. + * position: Position of the scrollbar withing the range. + */ +void API dw_scrollbar_set_pos(HWND handle, unsigned int position) +{ + dw_window_set_data(handle, "_dw_scrollbar_value", (void *)position); + WinSendMsg(handle, SBM_SETPOS, (MPARAM)position, 0); +} + +/* + * Sets the scrollbar range. + * Parameters: + * handle: Handle to the scrollbar to be set. + * range: Maximum range value. + * visible: Visible area relative to the range. + */ +void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible) +{ + unsigned int pos = (unsigned int)dw_window_get_data(handle, "_dw_scrollbar_value"); + WinSendMsg(handle, SBM_SETSCROLLBAR, (MPARAM)pos, MPFROM2SHORT(0, (unsigned short)range - visible)); + WinSendMsg(handle, SBM_SETTHUMBSIZE, MPFROM2SHORT((unsigned short)visible, range), 0); + dw_window_set_data(handle, "_dw_scrollbar_visible", (void *)visible); +} + +/* + * Sets the spinbutton value. + * Parameters: + * handle: Handle to the spinbutton to be set. + * position: Current value of the spinbutton. + */ +void API dw_spinbutton_set_pos(HWND handle, long position) +{ + WinSendMsg(handle, SPBM_SETCURRENTVALUE, MPFROMLONG((long)position), 0L); +} + +/* + * Sets the spinbutton limits. + * Parameters: + * handle: Handle to the spinbutton to be set. + * upper: Upper limit. + * lower: Lower limit. + */ +void API dw_spinbutton_set_limits(HWND handle, long upper, long lower) +{ + WinSendMsg(handle, SPBM_SETLIMITS, MPFROMLONG(upper), MPFROMLONG(lower)); +} + +/* + * Sets the entryfield character limit. + * Parameters: + * handle: Handle to the spinbutton to be set. + * limit: Number of characters the entryfield will take. + */ +void API dw_entryfield_set_limit(HWND handle, ULONG limit) +{ + WinSendMsg(handle, EM_SETTEXTLIMIT, (MPARAM)limit, (MPARAM)0); +} + + +/* + * Returns the current value of the spinbutton. + * Parameters: + * handle: Handle to the spinbutton to be queried. + */ +long API dw_spinbutton_get_pos(HWND handle) +{ + long tmpval = 0L; + + WinSendMsg(handle, SPBM_QUERYVALUE, (MPARAM)&tmpval,0L); + return tmpval; +} + +/* + * Returns the state of the checkbox. + * Parameters: + * handle: Handle to the checkbox to be queried. + */ +int API dw_checkbox_get(HWND handle) +{ + return (int)WinSendMsg(handle,BM_QUERYCHECK,0,0); +} + +/* + * Sets the state of the checkbox. + * Parameters: + * handle: Handle to the checkbox to be queried. + * value: TRUE for checked, FALSE for unchecked. + */ +void API dw_checkbox_set(HWND handle, int value) +{ + WinSendMsg(handle,BM_SETCHECK,MPFROMSHORT(value),0); +} + +/* + * Inserts an item into a tree window (widget) after another item. + * Parameters: + * handle: Handle to the tree to be inserted. + * item: Handle to the item to be positioned after. + * title: The text title of the entry. + * icon: Handle to coresponding icon. + * parent: Parent handle or 0 if root. + * itemdata: Item specific data. + */ +HTREEITEM API dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, HICN icon, HTREEITEM parent, void *itemdata) +{ + ULONG cbExtra; + PCNRITEM pci; + RECORDINSERT ri; + + if(!item) + item = (HTREEITEM)CMA_FIRST; + + /* Calculate extra bytes needed for each record besides that needed for the + * MINIRECORDCORE structure + */ + + cbExtra = sizeof(CNRITEM) - sizeof(MINIRECORDCORE); + + /* Allocate memory for the parent record */ + + if((pci = (PCNRITEM)_dw_send_msg(handle, CM_ALLOCRECORD, MPFROMLONG(cbExtra), MPFROMSHORT(1), 0)) == 0) + return 0; + + /* Fill in the parent record data */ + + pci->rc.cb = sizeof(MINIRECORDCORE); + pci->rc.pszIcon = strdup(title); + pci->rc.hptrIcon = icon; + + pci->hptrIcon = icon; + pci->user = itemdata; + pci->parent = parent; + + memset(&ri, 0, sizeof(RECORDINSERT)); + + ri.cb = sizeof(RECORDINSERT); + ri.pRecordOrder = (PRECORDCORE)item; + ri.zOrder = (USHORT)CMA_TOP; + ri.cRecordsInsert = 1; + ri.fInvalidateRecord = TRUE; + + /* We are about to insert the child records. Set the parent record to be + * the one we just inserted. + */ + ri.pRecordParent = (PRECORDCORE)parent; + + /* Insert the record */ + WinSendMsg(handle, CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri)); + + return (HTREEITEM)pci; +} + +/* + * Inserts an item into a tree window (widget). + * Parameters: + * handle: Handle to the tree to be inserted. + * title: The text title of the entry. + * icon: Handle to coresponding icon. + * parent: Parent handle or 0 if root. + * itemdata: Item specific data. + */ +HTREEITEM API dw_tree_insert(HWND handle, char *title, HICN icon, HTREEITEM parent, void *itemdata) +{ + return dw_tree_insert_after(handle, (HTREEITEM)CMA_END, title, icon, parent, itemdata); +} + +/* + * Sets the text and icon of an item in a tree window (widget). + * Parameters: + * handle: Handle to the tree containing the item. + * item: Handle of the item to be modified. + * title: The text title of the entry. + * icon: Handle to coresponding icon. + */ +void API dw_tree_item_change(HWND handle, HTREEITEM item, char *title, HICN icon) +{ + PCNRITEM pci = (PCNRITEM)item; + + if(!pci) + return; + + if(pci->rc.pszIcon) + free(pci->rc.pszIcon); + + pci->rc.pszIcon = strdup(title); + pci->rc.hptrIcon = icon; + + pci->hptrIcon = icon; + + WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pci, MPFROM2SHORT(1, CMA_TEXTCHANGED)); +} + +/* + * Gets the text an item in a tree window (widget). + * Parameters: + * handle: Handle to the tree containing the item. + * item: Handle of the item to be modified. + */ +char * API dw_tree_get_title(HWND handle, HTREEITEM item) +{ + PCNRITEM pci = (PCNRITEM)item; + + handle = handle; /* keep compiler happy */ + if(pci) + return pci->rc.pszIcon; + return NULL; +} + +/* + * Gets the text an item in a tree window (widget). + * Parameters: + * handle: Handle to the tree containing the item. + * item: Handle of the item to be modified. + */ +HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item) +{ + PCNRITEM pci = (PCNRITEM)item; + + handle = handle; /* keep compiler happy */ + if(pci) + return pci->parent; + return (HTREEITEM)0; +} + +/* + * Sets the item data of a tree item. + * Parameters: + * handle: Handle to the tree containing the item. + * item: Handle of the item to be modified. + * itemdata: User defined data to be associated with item. + */ +void API dw_tree_item_set_data(HWND handle, HTREEITEM item, void *itemdata) +{ + PCNRITEM pci = (PCNRITEM)item; + + handle = handle; /* keep compiler happy */ + if(!pci) + return; + + pci->user = itemdata; +} + +/* + * Gets the item data of a tree item. + * Parameters: + * handle: Handle to the tree containing the item. + * item: Handle of the item to be modified. + */ +void * API dw_tree_item_get_data(HWND handle, HTREEITEM item) +{ + PCNRITEM pci = (PCNRITEM)item; + + handle = handle; /* keep compiler happy */ + if(!pci) + return NULL; + return pci->user; +} + +/* + * Sets this item as the active selection. + * Parameters: + * handle: Handle to the tree window (widget) to be selected. + * item: Handle to the item to be selected. + */ +void API dw_tree_item_select(HWND handle, HTREEITEM item) +{ + PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); + + while(pCore) + { + if(pCore->flRecordAttr & CRA_SELECTED) + WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)pCore, MPFROM2SHORT(FALSE, CRA_SELECTED | CRA_CURSORED)); + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + } + WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)item, MPFROM2SHORT(TRUE, CRA_SELECTED | CRA_CURSORED)); + lastitem = 0; + lasthcnr = 0; +} + +/* + * Removes all nodes from a tree. + * Parameters: + * handle: Handle to the window (widget) to be cleared. + */ +void API dw_tree_clear(HWND handle) +{ + dw_container_clear(handle, TRUE); +} + +/* + * Expands a node on a tree. + * Parameters: + * handle: Handle to the tree window (widget). + * item: Handle to node to be expanded. + */ +void API dw_tree_item_expand(HWND handle, HTREEITEM item) +{ + WinSendMsg(handle, CM_EXPANDTREE, MPFROMP(item), 0); +} + +/* + * Collapses a node on a tree. + * Parameters: + * handle: Handle to the tree window (widget). + * item: Handle to node to be collapsed. + */ +void API dw_tree_item_collapse(HWND handle, HTREEITEM item) +{ + WinSendMsg(handle, CM_COLLAPSETREE, MPFROMP(item), 0); +} + +/* + * Removes a node from a tree. + * Parameters: + * handle: Handle to the window (widget) to be cleared. + * item: Handle to node to be deleted. + */ +void API dw_tree_item_delete(HWND handle, HTREEITEM item) +{ + PCNRITEM pci = (PCNRITEM)item; + + if(!item) + return; + + if(pci->rc.pszIcon) + { + free(pci->rc.pszIcon); + pci->rc.pszIcon = 0; + } + + WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)&pci, MPFROM2SHORT(1, CMA_INVALIDATE | CMA_FREE)); +} + +/* Some OS/2 specific container structs */ +typedef struct _containerinfo { + int count; + void *data; + HWND handle; +} ContainerInfo; + +/* + * Sets up the container columns. + * Parameters: + * handle: Handle to the container to be configured. + * flags: An array of unsigned longs with column flags. + * titles: An array of strings with column text titles. + * count: The number of columns (this should match the arrays). + * separator: The column number that contains the main separator. + * (this item may only be used in OS/2) + */ +int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator) +{ + PFIELDINFO details, first, left = NULL; + FIELDINFOINSERT detin; + CNRINFO cnri; + int z; + ULONG size = sizeof(RECORDCORE); + ULONG *offStruct = malloc(count * sizeof(ULONG)); + ULONG *tempflags = malloc((count+1) * sizeof(ULONG)); + WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); + ULONG *oldflags = blah ? blah->data : 0; + + if(!offStruct || !tempflags) + return FALSE; + + memcpy(tempflags, flags, count * sizeof(ULONG)); + tempflags[count] = 0; + + blah->data = tempflags; + blah->flags = separator; + + if(oldflags) + free(oldflags); + + while((first = (PFIELDINFO)WinSendMsg(handle, CM_QUERYDETAILFIELDINFO, 0, MPFROMSHORT(CMA_FIRST))) != NULL) + { + WinSendMsg(handle, CM_REMOVEDETAILFIELDINFO, (MPARAM)&first, MPFROM2SHORT(1, CMA_FREE)); + } + + /* Figure out the offsets to the items in the struct */ + for(z=0;z<count;z++) + { + offStruct[z] = size; + if(flags[z] & DW_CFA_BITMAPORICON) + size += sizeof(HPOINTER); + else if(flags[z] & DW_CFA_STRING) + size += sizeof(char *); + else if(flags[z] & DW_CFA_ULONG) + size += sizeof(ULONG); + else if(flags[z] & DW_CFA_DATE) + size += sizeof(CDATE); + else if(flags[z] & DW_CFA_TIME) + size += sizeof(CTIME); + } + + first = details = (PFIELDINFO)WinSendMsg(handle, CM_ALLOCDETAILFIELDINFO, MPFROMLONG(count), 0L); + + if(!first) + { + free(offStruct); + return FALSE; + } + + for(z=0;z<count;z++) + { + if(z==separator-1) + left=details; + details->cb = sizeof(FIELDINFO); + details->flData = flags[z]; + details->flTitle = CFA_FITITLEREADONLY; + details->pTitleData = titles[z]; + details->offStruct = offStruct[z]; + details = details->pNextFieldInfo; + } + + detin.cb = sizeof(FIELDINFOINSERT); + detin.fInvalidateFieldInfo = FALSE; + detin.pFieldInfoOrder = (PFIELDINFO) CMA_FIRST; + detin.cFieldInfoInsert = (ULONG)count; + + WinSendMsg(handle, CM_INSERTDETAILFIELDINFO, MPFROMP(first), MPFROMP(&detin)); + + if(count > separator && separator > 0) + { + cnri.cb = sizeof(CNRINFO); + cnri.pFieldInfoLast = left; + cnri.xVertSplitbar = 150; + + WinSendMsg(handle, CM_SETCNRINFO, MPFROMP(&cnri), MPFROMLONG(CMA_PFIELDINFOLAST | CMA_XVERTSPLITBAR)); + } + + cnri.flWindowAttr = CV_DETAIL | CV_MINI | CA_DETAILSVIEWTITLES; + cnri.slBitmapOrIcon.cx = 16; + cnri.slBitmapOrIcon.cy = 16; + + WinSendMsg(handle, CM_SETCNRINFO, &cnri, MPFROMLONG(CMA_FLWINDOWATTR | CMA_SLBITMAPORICON)); + + free(offStruct); + return DW_ERROR_NONE; +} + +/* + * Sets up the filesystem columns, note: filesystem always has an icon/filename field. + * Parameters: + * handle: Handle to the container to be configured. + * flags: An array of unsigned longs with column flags. + * titles: An array of strings with column text titles. + * count: The number of columns (this should match the arrays). + */ +int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count) +{ + char **newtitles = malloc(sizeof(char *) * (count + 2)); + unsigned long *newflags = malloc(sizeof(unsigned long) * (count + 2)); + + newtitles[0] = "Icon"; + newtitles[1] = "Filename"; + + newflags[0] = DW_CFA_BITMAPORICON | DW_CFA_CENTER | DW_CFA_HORZSEPARATOR | DW_CFA_SEPARATOR; + newflags[1] = DW_CFA_STRING | DW_CFA_LEFT | DW_CFA_HORZSEPARATOR; + + memcpy(&newtitles[2], titles, sizeof(char *) * count); + memcpy(&newflags[2], flags, sizeof(unsigned long) * count); + + dw_container_setup(handle, newflags, newtitles, count + 2, count ? 2 : 0); + + free(newtitles); + free(newflags); + return DW_ERROR_NONE; +} + +/* + * Obtains an icon from a module (or header in GTK). + * Parameters: + * module: Handle to module (DLL) in OS/2 and Windows. + * id: A unsigned long id int the resources on OS/2 and + * Windows, on GTK this is converted to a pointer + * to an embedded XPM. + */ +HICN API dw_icon_load(unsigned long module, unsigned long id) +{ + return WinLoadPointer(HWND_DESKTOP,module,id); +} + +/* + * Obtains an icon from a file. + * Parameters: + * filename: Name of the file, omit extention to have + * DW pick the appropriate file extension. + * (ICO on OS/2 or Windows, XPM on Unix) + */ +HICN API dw_icon_load_from_file(char *filename) +{ + char *file = alloca(strlen(filename) + 5); + + if(!file) + return 0; + + strcpy(file, filename); + + /* check if we can read from this file (it exists and read permission) */ + if(access(file, 04) != 0) + { + /* Try with .bmp extention */ + strcat(file, ".ico"); + if(access(file, 04) != 0) + return 0; + } + return WinLoadFileIcon(file, FALSE); +} + +/* + * Obtains an icon from data + * Parameters: + * filename: Name of the file, omit extention to have + * DW pick the appropriate file extension. + * (ICO on OS/2 or Windows, XPM on Unix) + */ +HICN API dw_icon_load_from_data(char *data, int len) +{ + HICN icon=0; + char *file; + FILE *fp; + + if ( !data ) + return 0; + file = tmpnam( NULL ); + if ( file != NULL ) + { + fp = fopen( file, "wb" ); + if ( fp != NULL ) + { + fwrite( data, 1, len, fp ); + fclose( fp ); + icon = WinLoadFileIcon( file, FALSE ); + } + else + { + unlink( file ); + return 0; + } + unlink( file ); + } + return icon; +} + +/* + * Frees a loaded resource in OS/2 and Windows. + * Parameters: + * handle: Handle to icon returned by dw_icon_load(). + */ +void API dw_icon_free(HICN handle) +{ + WinDestroyPointer(handle); +} + +/* + * Allocates memory used to populate a container. + * Parameters: + * handle: Handle to the container window (widget). + * rowcount: The number of items to be populated. + */ +void * API dw_container_alloc(HWND handle, int rowcount) +{ + WindowData *wd = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); + ULONG *flags = wd ? wd->data : 0; + int z, size = 0, totalsize, count = 0; + PRECORDCORE temp; + ContainerInfo *ci; + void *blah = NULL; + + if(!flags || rowcount < 1) + return NULL; + + while(flags[count]) + count++; + + /* Figure out the offsets to the items in the struct */ + for(z=0;z<count;z++) + { + if(flags[z] & DW_CFA_BITMAPORICON) + size += sizeof(HPOINTER); + else if(flags[z] & DW_CFA_STRING) + size += sizeof(char *); + else if(flags[z] & DW_CFA_ULONG) + size += sizeof(ULONG); + else if(flags[z] & DW_CFA_DATE) + size += sizeof(CDATE); + else if(flags[z] & DW_CFA_TIME) + size += sizeof(CTIME); + } + + totalsize = size + sizeof(RECORDCORE); + + z = 0; + + if(!(blah = (void *)_dw_send_msg(handle, CM_ALLOCRECORD, MPFROMLONG(size), MPFROMLONG(rowcount), 0))) + return NULL; + + temp = (PRECORDCORE)blah; + + for(z=0;z<rowcount;z++) + { + temp->cb = totalsize; + temp = temp->preccNextRecord; + } + + ci = malloc(sizeof(struct _containerinfo)); + + ci->count = rowcount; + ci->data = blah; + ci->handle = handle; + + return (void *)ci; +} + +/* Internal function that does the work for set_item and change_item */ +void _dw_container_set_item(HWND handle, PRECORDCORE temp, int column, int row, void *data) +{ + WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); + ULONG totalsize, size = 0, *flags = blah ? blah->data : 0; + int z, currentcount; + CNRINFO cnr; + void *dest; + + if(!flags) + return; + + if(!_dw_send_msg(handle, CM_QUERYCNRINFO, (MPARAM)&cnr, MPFROMSHORT(sizeof(CNRINFO)), 0)) + return; + + currentcount = cnr.cRecords; + + /* Figure out the offsets to the items in the struct */ + for(z=0;z<column;z++) + { + if(flags[z] & DW_CFA_BITMAPORICON) + size += sizeof(HPOINTER); + else if(flags[z] & DW_CFA_STRING) + size += sizeof(char *); + else if(flags[z] & DW_CFA_ULONG) + size += sizeof(ULONG); + else if(flags[z] & DW_CFA_DATE) + size += sizeof(CDATE); + else if(flags[z] & DW_CFA_TIME) + size += sizeof(CTIME); + } + + totalsize = size + sizeof(RECORDCORE); + + for(z=0;z<(row-currentcount);z++) + temp = temp->preccNextRecord; + + dest = (void *)(((ULONG)temp)+((ULONG)totalsize)); + + if(flags[column] & DW_CFA_BITMAPORICON) + memcpy(dest, data, sizeof(HPOINTER)); + else if(flags[column] & DW_CFA_STRING) + { + char **newstr = (char **)data, **str = dest; + + if(*str) + free(*str); + + if(newstr && *newstr) + *str = strdup(*newstr); + else + *str = NULL; + } + else if(flags[column] & DW_CFA_ULONG) + memcpy(dest, data, sizeof(ULONG)); + else if(flags[column] & DW_CFA_DATE) + memcpy(dest, data, sizeof(CDATE)); + else if(flags[column] & DW_CFA_TIME) + memcpy(dest, data, sizeof(CTIME)); +} + +/* Internal function that free()s any strings allocated for a container item */ +void _dw_container_free_strings(HWND handle, PRECORDCORE temp) +{ + WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); + ULONG totalsize, size = 0, *flags = blah ? blah->data : 0; + int z, count = 0; + + if(!flags) + return; + + while(flags[count]) + count++; + + /* Figure out the offsets to the items in the struct */ + for(z=0;z<count;z++) + { + if(flags[z] & DW_CFA_BITMAPORICON) + size += sizeof(HPOINTER); + else if(flags[z] & DW_CFA_STRING) + { + char **str; + + totalsize = size + sizeof(RECORDCORE); + + str = (char **)(((ULONG)temp)+((ULONG)totalsize)); + + if(*str) + { + free(*str); + *str = NULL; + } + size += sizeof(char *); + } + else if(flags[z] & DW_CFA_ULONG) + size += sizeof(ULONG); + else if(flags[z] & DW_CFA_DATE) + size += sizeof(CDATE); + else if(flags[z] & DW_CFA_TIME) + size += sizeof(CTIME); + } +} + +/* + * Sets an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data) +{ + ContainerInfo *ci = (ContainerInfo *)pointer; + + if(!ci) + return; + + _dw_container_set_item(handle, (PRECORDCORE)ci->data, column, row, data); +} + +/* + * Changes an existing item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_container_change_item(HWND handle, int column, 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) + { + _dw_container_set_item(handle, pCore, column, 0, data); + WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_NOREPOSITION | CMA_TEXTCHANGED)); + return; + } + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + count++; + } +} + +/* + * Changes an existing item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_filesystem_change_item(HWND handle, int column, int row, void *data) +{ + dw_container_change_item(handle, column + 2, row, data); +} + +/* + * Changes an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_filesystem_change_file(HWND handle, int row, char *filename, HICN icon) +{ + dw_container_change_item(handle, 0, row, (void *)&icon); + dw_container_change_item(handle, 1, row, (void *)&filename); +} + +/* + * Sets an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, HICN icon) +{ + dw_container_set_item(handle, pointer, 0, row, (void *)&icon); + dw_container_set_item(handle, pointer, 1, row, (void *)&filename); +} + +/* + * Sets an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data) +{ + dw_container_set_item(handle, pointer, column + 2, row, data); +} + +/* + * Gets column type for a container column + * Parameters: + * handle: Handle to the container window (widget). + * column: Zero based column. + */ +int API dw_container_get_column_type(HWND handle, int column) +{ + WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); + ULONG *flags = blah ? blah->data : 0; + int rc; + + if(!flags) + return 0; + + if(flags[column] & DW_CFA_BITMAPORICON) + rc = DW_CFA_BITMAPORICON; + else if(flags[column] & DW_CFA_STRING) + rc = DW_CFA_STRING; + else if(flags[column] & DW_CFA_ULONG) + rc = DW_CFA_ULONG; + else if(flags[column] & DW_CFA_DATE) + rc = DW_CFA_DATE; + else if(flags[column] & DW_CFA_TIME) + rc = DW_CFA_TIME; + else + rc = 0; + return rc; +} + +/* + * Gets column type for a filesystem container column + * Parameters: + * handle: Handle to the container window (widget). + * column: Zero based column. + */ +int API dw_filesystem_get_column_type(HWND handle, int column) +{ + return dw_container_get_column_type( handle, column + 2 ); +} + +/* + * Sets the alternating row colors for container window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * oddcolor: Odd row background color in DW_RGB format or a default color index. + * evencolor: Even row background color in DW_RGB format or a default color index. + * DW_RGB_TRANSPARENT will disable coloring rows. + * DW_CLR_DEFAULT will use the system default alternating row colors. + */ +void API dw_container_set_stripe(HWND handle, unsigned long oddcolor, unsigned long evencolor) +{ + /* Don't think this is possible on OS/2 */ +} + +/* + * Sets the width of a column in the container. + * Parameters: + * handle: Handle to window (widget) of container. + * column: Zero based column of width being set. + * width: Width of column in pixels. + */ +void API dw_container_set_column_width(HWND handle, int column, int width) +{ + handle = handle; /* keep compiler happy */ + column = column; /* keep compiler happy */ + width = width; /* keep compiler happy */ +} + +/* + * Sets the title 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. + * title: String title of the item. + */ +void API dw_container_set_row_title(void *pointer, int row, char *title) +{ + 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->pszIcon = title; + temp->pszName = title; + temp->pszText = title; +} + +/* + * Changes the title of a row already inserted in the container. + * Parameters: + * handle: Handle to the container window (widget). + * row: Zero based row of data being set. + * title: String title of the item. + */ +void API dw_container_change_row_title(HWND handle, int row, char *title) +{ + PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); + int count = 0; + + while(pCore) + { + if(count == row) + { + pCore->pszIcon = title; + pCore->pszName = title; + pCore->pszText = title; + + WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_NOREPOSITION | CMA_TEXTCHANGED)); + return; + } + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + count++; + } +} + +/* Internal function to get the first item with given flags */ +PRECORDCORE _dw_container_start(HWND handle, unsigned long flags) +{ + PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); + + if(pCore) + { + while(pCore) + { + if(pCore->flRecordAttr & flags) + { + return pCore; + } + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + } + } + return NULL; +} + +/* + * Sets the title of a row in the container. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * rowcount: The number of rows to be inserted. + */ +void API dw_container_insert(HWND handle, void *pointer, int rowcount) +{ + RECORDINSERT recin; + ContainerInfo *ci = (ContainerInfo *)pointer; + PRECORDCORE pCore; + + if(!ci) + return; + + recin.cb = sizeof(RECORDINSERT); + recin.pRecordOrder = (PRECORDCORE)CMA_END; + recin.pRecordParent = NULL; + recin.zOrder = CMA_TOP; + recin.fInvalidateRecord = TRUE; + recin.cRecordsInsert = rowcount; + + _dw_send_msg(handle, CM_INSERTRECORD, MPFROMP(ci->data), MPFROMP(&recin), 0); + + free(ci); + + if((pCore = _dw_container_start(handle, CRA_CURSORED))) + { + NOTIFYRECORDEMPHASIS pre; + + pre.pRecord = pCore; + pre.fEmphasisMask = CRA_CURSORED; + pre.hwndCnr = handle; + _run_event(handle, WM_CONTROL, MPFROM2SHORT(0, CN_EMPHASIS), (MPARAM)&pre); + pre.pRecord->flRecordAttr |= CRA_CURSORED; + } +} + +/* + * Removes all rows from a container. + * Parameters: + * handle: Handle to the window (widget) to be cleared. + * redraw: TRUE to cause the container to redraw immediately. + */ +void API dw_container_clear(HWND handle, int redraw) +{ + PCNRITEM pCore; + int container = (int)dw_window_get_data(handle, "_dw_container"); + + if(hwndEmph == handle) + _clear_emphasis(); + + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); + + while(pCore) + { + if(container) + _dw_container_free_strings(handle, (PRECORDCORE)pCore); + else + { + /* Free icon text */ + if(pCore->rc.pszIcon) + { + free(pCore->rc.pszIcon); + pCore->rc.pszIcon = 0; + } + } + pCore = (PCNRITEM)pCore->rc.preccNextRecord;/*WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));*/ + } + _dw_send_msg(handle, CM_REMOVERECORD, (MPARAM)0L, MPFROM2SHORT(0, (redraw ? CMA_INVALIDATE : 0) | CMA_FREE), -1); +} + +/* + * Removes the first x rows from a container. + * Parameters: + * handle: Handle to the window (widget) to be deleted from. + * rowcount: The number of rows to be deleted. + */ +void API dw_container_delete(HWND handle, int rowcount) +{ + RECORDCORE *last, **prc = malloc(sizeof(RECORDCORE *) * rowcount); + int current = 1; + + prc[0] = last = (RECORDCORE *)WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); + + while(last && current < rowcount) + { + _dw_container_free_strings(handle, last); + prc[current] = last = (RECORDCORE *)WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)last, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + current++; + } + + _dw_send_msg(handle, CM_REMOVERECORD, (MPARAM)prc, MPFROM2SHORT(current, CMA_INVALIDATE | CMA_FREE), -1); + + free(prc); +} + +/* + * Scrolls container up or down. + * Parameters: + * handle: Handle to the window (widget) to be scrolled. + * direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or + * DW_SCROLL_BOTTOM. (rows is ignored for last two) + * rows: The number of rows to be scrolled. + */ +void API dw_container_scroll(HWND handle, int direction, long rows) +{ + rows = rows; /* keep compiler happy */ + switch(direction) + { + case DW_SCROLL_TOP: + WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(-10000000)); + break; + case DW_SCROLL_BOTTOM: + WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(10000000)); + break; + } +} + +/* + * Starts a new query of a container. + * Parameters: + * handle: Handle to the window (widget) to be queried. + * flags: If this parameter is DW_CRA_SELECTED it will only + * return items that are currently selected. Otherwise + * it will return all records in the container. + */ +char * API dw_container_query_start(HWND handle, unsigned long flags) +{ + PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); + + if(pCore) + { + if(flags) + { + while(pCore) + { + if(pCore->flRecordAttr & flags) + { + dw_window_set_data(handle, "_dw_pcore", (void *)pCore); + return pCore->pszIcon; + } + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + } + } + else + { + dw_window_set_data(handle, "_dw_pcore", (void *)pCore); + return pCore->pszIcon; + } + } + return NULL; +} + +/* + * Continues an existing query of a container. + * Parameters: + * handle: Handle to the window (widget) to be queried. + * flags: If this parameter is DW_CRA_SELECTED it will only + * return items that are currently selected. Otherwise + * it will return all records in the container. + */ +char * API dw_container_query_next(HWND handle, unsigned long flags) +{ + PRECORDCORE pCore = (PRECORDCORE)dw_window_get_data(handle, "_dw_pcore"); + + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + + if(pCore) + { + if(flags) + { + while(pCore) + { + if(pCore->flRecordAttr & flags) + { + dw_window_set_data(handle, "_dw_pcore", (void *)pCore); + return pCore->pszIcon; + } + + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + } + } + else + { + dw_window_set_data(handle, "_dw_pcore", (void *)pCore); + return pCore->pszIcon; + } + } + return NULL; +} + +/* + * 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(HWND handle, char *text) +{ + 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(pCore->pszIcon, text) == 0) || (!textcomp && (char *)pCore->pszIcon == text)) + { + 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 text speficied. + * Parameters: + * handle: Handle to the window (widget). + * text: Text usually returned by dw_container_query(). + */ +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((textcomp && pCore->pszIcon && strcmp(pCore->pszIcon, text) == 0) || (!textcomp && (char *)pCore->pszIcon == text)) + { + 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)); + } +} + +/* + * Optimizes the column widths so that all data is visible. + * Parameters: + * handle: Handle to the window (widget) to be optimized. + */ +void API dw_container_optimize(HWND handle) +{ + WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER); + RECTL item; + PRECORDCORE pCore = NULL; + int max = 0; + + if(blah && !blah->flags) + return; + + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); + while(pCore) + { + QUERYRECORDRECT qrr; + int vector; + + qrr.cb = sizeof(QUERYRECORDRECT); + qrr.pRecord = pCore; + qrr.fRightSplitWindow = 0; + qrr.fsExtent = CMA_TEXT; + + WinSendMsg(handle, CM_QUERYRECORDRECT, (MPARAM)&item, (MPARAM)&qrr); + + vector = item.xRight - item.xLeft; + + if(vector > max) + max = vector; + + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + } + + if(max) + { + CNRINFO cnri; + + cnri.cb = sizeof(CNRINFO); + cnri.xVertSplitbar = max; + + WinSendMsg(handle, CM_SETCNRINFO, MPFROMP(&cnri), MPFROMLONG(CMA_XVERTSPLITBAR)); + } +} + +/* + * Inserts an icon into the taskbar. + * Parameters: + * handle: Window handle that will handle taskbar icon messages. + * icon: Icon handle to display in the taskbar. + * bubbletext: Text to show when the mouse is above the icon. + */ +void API dw_taskbar_insert(HWND handle, HICN icon, char *bubbletext) +{ + /* Make sure we have our server */ + if(!hwndTrayServer) + return; + + WinSendMsg(hwndApp, WM_SETICON, (MPARAM)icon, 0); + hwndTaskBar = handle; + WinPostMsg(hwndTrayServer, WM_USER+1, (MPARAM)hwndApp, (MPARAM)icon); +} + +/* + * Deletes an icon from the taskbar. + * Parameters: + * handle: Window handle that was used with dw_taskbar_insert(). + * icon: Icon handle that was used with dw_taskbar_insert(). + */ +void API dw_taskbar_delete(HWND handle, HICN icon) +{ + /* Make sure we have our server */ + if(!hwndTrayServer) + return; + + WinPostMsg(hwndTrayServer, WM_USER+2, (MPARAM)hwndApp, (MPARAM)0); + hwndTaskBar = NULLHANDLE; +} + +/* + * Creates a rendering context widget (window) to be packed. + * Parameters: + * id: An id to be used with dw_window_from_id. + * Returns: + * A handle to the widget or NULL on failure. + */ +HWND API dw_render_new(unsigned long id) +{ + HWND hwndframe = WinCreateWindow(HWND_OBJECT, + WC_FRAME, + NULL, + WS_VISIBLE | + FS_NOBYTEALIGN, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + WinSubclassWindow(hwndframe, _RendProc); + return hwndframe; +} + +/* Sets the current foreground drawing color. + * Parameters: + * red: red value. + * green: green value. + * blue: blue value. + */ +void API dw_color_foreground_set(unsigned long value) +{ + _foreground = value; +} + +/* Sets the current background drawing color. + * Parameters: + * red: red value. + * green: green value. + * blue: blue value. + */ +void API dw_color_background_set(unsigned long value) +{ + _background = value; +} + +int DWSIGNAL _dw_color_cancel_func(HWND window, void *data) +{ + DWDialog *dwwait = (DWDialog *)data; + HMTX mtx = (HMTX)dw_window_get_data((HWND)dwwait->data, "_dw_mutex"); + void *val; + + window = (HWND)dwwait->data; + val = dw_window_get_data(window, "_dw_val"); + + dw_mutex_lock(mtx); + dw_mutex_close(mtx); + dw_window_destroy(window); + dw_dialog_dismiss((DWDialog *)data, val); + return FALSE; +} + +int DWSIGNAL _dw_color_ok_func(HWND window, void *data) +{ + DWDialog *dwwait = (DWDialog *)data; + HMTX mtx = (HMTX)dw_window_get_data((HWND)dwwait->data, "_dw_mutex"); + unsigned long val; + + window = (HWND)dwwait->data; + val = _dw_color_spin_get(window); + + dw_mutex_lock(mtx); + dw_mutex_close(mtx); + dw_window_destroy(window); + dw_dialog_dismiss((DWDialog *)data, (void *)val); + return FALSE; +} + +/* Allows the user to choose a color using the system's color chooser dialog. + * Parameters: + * value: current color + * Returns: + * The selected color or the current color if cancelled. + */ +unsigned long API dw_color_choose(unsigned long value) +{ + HWND window, hbox, vbox, col, button, text; + DWDialog *dwwait; + HMTX mtx = dw_mutex_new(); + + window = dw_window_new( HWND_DESKTOP, "Choose Color", FCF_SHELLPOSITION | FCF_TITLEBAR | FCF_DLGBORDER | FCF_CLOSEBUTTON | FCF_SYSMENU); + + vbox = dw_box_new(DW_VERT, 5); + + dw_box_pack_start(window, vbox, 0, 0, TRUE, TRUE, 0); + + hbox = dw_box_new(DW_HORZ, 0); + + dw_box_pack_start(vbox, hbox, 0, 0, FALSE, FALSE, 0); + dw_window_set_style(hbox, 0, WS_CLIPCHILDREN); + + col = WinCreateWindow(vbox, "ColorSelectClass", "", WS_VISIBLE | WS_GROUP, 0, 0, 390, 300, vbox, HWND_TOP, 266, NULL,NULL); + dw_box_pack_start(hbox, col, 390, 300, FALSE, FALSE, 0); + + dw_window_set_data(hbox, "_dw_window", (void *)window); + dw_window_set_data(window, "_dw_mutex", (void *)mtx); + dw_window_set_data(window, "_dw_col", (void *)col); + dw_window_set_data(window, "_dw_val", (void *)value); + + hbox = dw_box_new(DW_HORZ, 0); + dw_window_set_data(hbox, "_dw_window", (void *)window); + + dw_box_pack_start(vbox, hbox, 0, 0, TRUE, FALSE, 0); + + text = dw_text_new("Red:", 0); + dw_window_set_style(text, DW_DT_VCENTER, DW_DT_VCENTER); + dw_box_pack_start(hbox, text, 30, 20, FALSE, FALSE, 3); + + button = dw_spinbutton_new("", 1001L); + dw_spinbutton_set_limits(button, 255, 0); + dw_box_pack_start(hbox, button, 20, 20, TRUE, FALSE, 3); + WinSetOwner(button, hbox); + dw_window_set_data(window, "_dw_red_spin", (void *)button); + + text = dw_text_new("Green:", 0); + dw_window_set_style(text, DW_DT_VCENTER, DW_DT_VCENTER); + dw_box_pack_start(hbox, text, 30, 20, FALSE, FALSE, 3); + + button = dw_spinbutton_new("", 1002L); + dw_spinbutton_set_limits(button, 255, 0); + dw_box_pack_start(hbox, button, 20, 20, TRUE, FALSE, 3); + WinSetOwner(button, hbox); + dw_window_set_data(window, "_dw_green_spin", (void *)button); + + text = dw_text_new("Blue:", 0); + dw_window_set_style(text, DW_DT_VCENTER, DW_DT_VCENTER); + dw_box_pack_start(hbox, text, 30, 20, FALSE, FALSE, 3); + + button = dw_spinbutton_new("", 1003L); + dw_spinbutton_set_limits(button, 255, 0); + dw_box_pack_start(hbox, button, 20, 20, TRUE, FALSE, 3); + WinSetOwner(button, hbox); + dw_window_set_data(window, "_dw_blue_spin", (void *)button); + + hbox = dw_box_new(DW_HORZ, 0); + + dw_box_pack_start(vbox, hbox, 0, 0, TRUE, FALSE, 0); + dw_box_pack_start(hbox, 0, 100, 1, TRUE, FALSE, 0); + + button = dw_button_new("Ok", 1001L); + dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3); + + dwwait = dw_dialog_new((void *)window); + + dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_color_ok_func), (void *)dwwait); + + button = dw_button_new("Cancel", 1002L); + dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3); + + dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_color_cancel_func), (void *)dwwait); + dw_signal_connect(window, DW_SIGNAL_DELETE, DW_SIGNAL_FUNC(_dw_color_cancel_func), (void *)dwwait); + + dw_window_set_size(window, 400, 400); + + _dw_col_set(col, value); + _dw_color_spin_set(window, value); + + dw_window_show(window); + + return (unsigned long)dw_dialog_wait(dwwait); +} + +HPS _set_hps(HPS hps) +{ + LONG alTable[2]; + + alTable[0] = DW_RED_VALUE(_foreground) << 16 | DW_GREEN_VALUE(_foreground) << 8 | DW_BLUE_VALUE(_foreground); + alTable[1] = DW_RED_VALUE(_background) << 16 | DW_GREEN_VALUE(_background) << 8 | DW_BLUE_VALUE(_background); + + GpiCreateLogColorTable(hps, + LCOL_RESET, + LCOLF_CONSECRGB, + 16, + 2, + alTable); + if(_foreground & DW_RGB_COLOR) + GpiSetColor(hps, 16); + else + GpiSetColor(hps, _internal_color(_foreground)); + if(_background & DW_RGB_COLOR) + GpiSetBackColor(hps, 17); + else + GpiSetBackColor(hps, _internal_color(_background)); + return hps; +} + +HPS _set_colors(HWND handle) +{ + HPS hps = WinGetPS(handle); + + _set_hps(hps); + return hps; +} + +/* Draw a point on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * x: X coordinate. + * y: Y coordinate. + */ +void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y) +{ + HPS hps; + int height; + POINTL ptl; + + if(handle) + { + hps = _set_colors(handle); + height = _get_height(handle); + } + else if(pixmap) + { + hps = _set_hps(pixmap->hps); + height = pixmap->height; + } + else + return; + + ptl.x = x; + ptl.y = height - y - 1; + + GpiSetPel(hps, &ptl); + if(!pixmap) + WinReleasePS(hps); +} + +/* Draw a line on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * x1: First X coordinate. + * y1: First Y coordinate. + * x2: Second X coordinate. + * y2: Second Y coordinate. + */ +void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2) +{ + HPS hps; + int height; + POINTL ptl[2]; + + if(handle) + { + hps = _set_colors(handle); + height = _get_height(handle); + } + else if(pixmap) + { + hps = _set_hps(pixmap->hps); + height = pixmap->height; + } + else + return; + + ptl[0].x = x1; + ptl[0].y = height - y1 - 1; + ptl[1].x = x2; + ptl[1].y = height - y2 - 1; + + GpiMove(hps, &ptl[0]); + GpiLine(hps, &ptl[1]); + + if(!pixmap) + WinReleasePS(hps); +} + + +void _CopyFontSettings(HPS hpsSrc, HPS hpsDst) +{ + FONTMETRICS fm; + FATTRS fat; + SIZEF sizf; + + GpiQueryFontMetrics(hpsSrc, sizeof(FONTMETRICS), &fm); + + memset(&fat, 0, sizeof(fat)); + + fat.usRecordLength = sizeof(FATTRS); + fat.lMatch = fm.lMatch; + strcpy(fat.szFacename, fm.szFacename); + + GpiCreateLogFont(hpsDst, 0, 1L, &fat); + GpiSetCharSet(hpsDst, 1L); + + sizf.cx = MAKEFIXED(fm.lEmInc,0); + sizf.cy = MAKEFIXED(fm.lMaxBaselineExt,0); + GpiSetCharBox(hpsDst, &sizf ); +} + +/* Draw text on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * x: X coordinate. + * y: Y coordinate. + * text: Text to be displayed. + */ +void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text) +{ + HPS hps; + int z, height; + RECTL rcl; + char fontname[128]; + POINTL aptl[TXTBOX_COUNT]; + + if(handle) + { + hps = _set_colors(handle); + height = _get_height(handle); + _GetPPFont(handle, fontname); + } + else if(pixmap) + { + HPS pixmaphps = WinGetPS(pixmap->font ? pixmap->font : pixmap->handle); + + hps = _set_hps(pixmap->hps); + height = pixmap->height; + _GetPPFont(pixmap->font ? pixmap->font : pixmap->handle, fontname); + _CopyFontSettings(pixmaphps, hps); + WinReleasePS(pixmaphps); + } + else + return; + + for(z=0;z<strlen(fontname);z++) + { + if(fontname[z]=='.') + break; + } + + GpiQueryTextBox(hps, strlen(text), text, TXTBOX_COUNT, aptl); + + rcl.xLeft = x; + rcl.yTop = height - y; + rcl.yBottom = rcl.yTop - (aptl[TXTBOX_TOPLEFT].y - aptl[TXTBOX_BOTTOMLEFT].y); + rcl.xRight = rcl.xLeft + (aptl[TXTBOX_TOPRIGHT].x - aptl[TXTBOX_TOPLEFT].x); + + if(_background == DW_CLR_DEFAULT) + WinDrawText(hps, -1, text, &rcl, DT_TEXTATTRS, DT_TEXTATTRS, DT_VCENTER | DT_LEFT | DT_TEXTATTRS); + else + WinDrawText(hps, -1, text, &rcl, _internal_color(_foreground), _internal_color(_background), DT_VCENTER | DT_LEFT | DT_ERASERECT); + + if(!pixmap) + WinReleasePS(hps); +} + +/* Query the width and height of a text string. + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * text: Text to be queried. + * width: Pointer to a variable to be filled in with the width. + * height Pointer to a variable to be filled in with the height. + */ +void API dw_font_text_extents_get(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height) +{ + HPS hps; + POINTL aptl[TXTBOX_COUNT]; + + if(handle) + { + hps = _set_colors(handle); + } + else if(pixmap) + { + HPS pixmaphps = WinGetPS(pixmap->font ? pixmap->font : pixmap->handle); + + hps = _set_hps(pixmap->hps); + _CopyFontSettings(pixmaphps, hps); + WinReleasePS(pixmaphps); + } + else + return; + + GpiQueryTextBox(hps, strlen(text), text, TXTBOX_COUNT, aptl); + + if(width) + *width = aptl[TXTBOX_TOPRIGHT].x - aptl[TXTBOX_TOPLEFT].x; + + if(height) + *height = aptl[TXTBOX_TOPLEFT].y - aptl[TXTBOX_BOTTOMLEFT].y; + + if(!pixmap) + WinReleasePS(hps); +} + +/* Draw a polygon on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * flags: DW_DRAW_FILL (1) to fill the polygon or DW_DRAW_DEFAULT (0). + * x: X coordinate. + * y: Y coordinate. + * width: Width of rectangle. + * height: Height of rectangle. + */ +void API dw_draw_polygon( HWND handle, HPIXMAP pixmap, int flags, int npoints, int *x, int *y ) +{ + HPS hps; + int thisheight; + POINTL *pptl; + POINTL start; + int i; + + if(handle) + { + hps = _set_colors(handle); + thisheight = _get_height(handle); + } + else if(pixmap) + { + hps = _set_hps(pixmap->hps); + thisheight = pixmap->height; + } + else + return; + if ( npoints == 0 ) + return; + pptl = (POINTL *)malloc(sizeof(POINTL)*npoints); + if ( pptl == NULL ) + return; + /* + * For a filled polygon we need to start an area + */ + if ( flags & DW_DRAW_FILL ) + GpiBeginArea( hps, 0L ); + if ( npoints ) + { + /* + * Move to the first point of the polygon + */ + start.x = x[0]; + start.y = thisheight - y[0] - 1; + GpiMove( hps, &start ); + /* + * Convert the remainder of the x and y points + */ + for ( i = 1; i < npoints; i++ ) + { + pptl[i-1].x = x[i]; + pptl[i-1].y = thisheight - y[i] - 1; + } + GpiPolyLine( hps, npoints-1, pptl ); + + if ( flags & DW_DRAW_FILL ) + GpiEndArea( hps ); + } + if ( !pixmap ) + WinReleasePS(hps); + free( pptl ); +} + +/* Draw a rectangle on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * flags: DW_DRAW_FILL (1) to fill the box or DW_DRAW_DEFAULT (0). + * x: X coordinate. + * y: Y coordinate. + * width: Width of rectangle. + * height: Height of rectangle. + */ +void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int flags, int x, int y, int width, int height) +{ + HPS hps; + int thisheight; + POINTL ptl[2]; + + if(handle) + { + hps = _set_colors(handle); + thisheight = _get_height(handle); + } + else if(pixmap) + { + hps = _set_hps(pixmap->hps); + thisheight = pixmap->height; + } + else + return; + + ptl[0].x = x; + ptl[0].y = thisheight - y - 1; + ptl[1].x = x + width - 1; + ptl[1].y = thisheight - y - height; + + GpiMove(hps, &ptl[0]); + GpiBox(hps, (flags & DW_DRAW_FILL) ? DRO_OUTLINEFILL : DRO_OUTLINE, &ptl[1], 0, 0); + + if(!pixmap) + WinReleasePS(hps); +} + +/* VisualAge doesn't seem to have this */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +/* Draw an arc on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * flags: DW_DRAW_FILL (1) to fill the arc or DW_DRAW_DEFAULT (0). + * DW_DRAW_FULL will draw a complete circle/elipse. + * xorigin: X coordinate of center of arc. + * yorigin: Y coordinate of center of arc. + * x1: X coordinate of first segment of arc. + * y1: Y coordinate of first segment of arc. + * x2: X coordinate of second segment of arc. + * y2: Y coordinate of second segment of arc. + */ +void API dw_draw_arc(HWND handle, HPIXMAP pixmap, int flags, int xorigin, int yorigin, int x1, int y1, int x2, int y2) +{ + HPS hps; + int thisheight; + ARCPARAMS ap = { 1, 1, 0, 0 }; + POINTL pts[2]; + double r, a1, a2, a; + + if(handle) + { + hps = _set_colors(handle); + thisheight = _get_height(handle); + } + else if(pixmap) + { + hps = _set_hps(pixmap->hps); + thisheight = pixmap->height; + } + else + return; + + /* Handle full circle/ellipse */ + if(flags & DW_DRAW_FULL) + { + pts[0].x = xorigin; + pts[0].y = thisheight - yorigin - 1; + GpiMove(hps, pts); + ap.lP = (x2 - x1)/2; + ap.lQ = (y2 - y1)/2; + /* Setup the arc info on the presentation space */ + GpiSetArcParams(hps, &ap); + GpiFullArc(hps, (flags & DW_DRAW_FILL) ? DRO_OUTLINEFILL : DRO_OUTLINE, MAKEFIXED(1, 1)); + } + else + { + /* For a filled arc we need to start an area */ + if(flags & DW_DRAW_FILL) + GpiBeginArea(hps, 0L); + + /* Setup the default arc info on the presentation space */ + GpiSetArcParams(hps, &ap); + pts[0].x = x1; + pts[0].y = thisheight - y1 - 1; + /* Move to the initial position */ + GpiMove(hps, pts); + /* Calculate the midpoint */ + r = 0.5 * (hypot((double)(y1 - yorigin), (double)(x1 - xorigin)) + + hypot((double)(y2 - yorigin), (double)(x2 - xorigin))); + a1 = atan2((double)(y1 - yorigin), (double)(x1 - xorigin)); + a2 = atan2((double)(y2 - yorigin), (double)(x2 - xorigin)); + if(a2 < a1) + a2 += M_PI * 2; + a = (a1 + a2) / 2.; + /* Prepare to draw */ + pts[0].x = (int)(xorigin + r * cos(a)); + pts[0].y = thisheight - (int)(yorigin + r * sin(a)) - 1; + pts[1].x = x2; + pts[1].y = thisheight - y2 - 1; + /* Actually draw the arc */ + GpiPointArc(hps, pts); + if(flags & DW_DRAW_FILL) + GpiEndArea(hps); + } + + if(!pixmap) + WinReleasePS(hps); +} + +/* Call this after drawing to the screen to make sure + * anything you have drawn is visible. + */ +void API dw_flush(void) +{ +} + +/* + * Creates a pixmap with given parameters. + * Parameters: + * handle: Window handle the pixmap is associated with. + * width: Width of the pixmap in pixels. + * height: Height of the pixmap in pixels. + * depth: Color depth of the pixmap. + * Returns: + * A handle to a pixmap or NULL on failure. + */ +HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth) +{ + BITMAPINFOHEADER bmih; + SIZEL sizl = { 0, 0 }; + HPIXMAP pixmap; + HDC hdc; + HPS hps; + ULONG ulFlags; + LONG cPlanes, cBitCount; + + if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) + return NULL; + + hps = WinGetPS(handle); + + hdc = GpiQueryDevice(hps); + ulFlags = GpiQueryPS(hps, &sizl); + + pixmap->handle = handle; + pixmap->hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc); + pixmap->hps = GpiCreatePS (dwhab, pixmap->hdc, &sizl, ulFlags | GPIA_ASSOC); + + DevQueryCaps(hdc, CAPS_COLOR_PLANES , 1L, &cPlanes); + if (!depth) + { + DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1L, &cBitCount); + depth = cBitCount; + } + + memset(&bmih, 0, sizeof(BITMAPINFOHEADER)); + bmih.cbFix = sizeof(BITMAPINFOHEADER); + bmih.cx = (SHORT)width; + bmih.cy = (SHORT)height; + bmih.cPlanes = (SHORT)cPlanes; + bmih.cBitCount = (SHORT)depth; + + pixmap->width = width; pixmap->height = height; + pixmap->transcolor = DW_CLR_DEFAULT; + + pixmap->hbm = GpiCreateBitmap(pixmap->hps, (PBITMAPINFOHEADER2)&bmih, 0L, NULL, NULL); + + GpiSetBitmap(pixmap->hps, pixmap->hbm); + + if (depth>8) + GpiCreateLogColorTable(pixmap->hps, LCOL_PURECOLOR, LCOLF_RGB, 0, 0, NULL ); + + WinReleasePS(hps); + + return pixmap; +} + +/* + * Creates a pixmap from a file. + * Parameters: + * handle: Window handle the pixmap is associated with. + * filename: Name of the file, omit extention to have + * DW pick the appropriate file extension. + * (BMP on OS/2 or Windows, XPM on Unix) + * Returns: + * A handle to a pixmap or NULL on failure. + */ +HPIXMAP API dw_pixmap_new_from_file(HWND handle, char *filename) +{ + HPIXMAP pixmap; + char *file = alloca(strlen(filename) + 5); + + if ( !file || !(pixmap = calloc(1,sizeof(struct _hpixmap))) ) + return NULL; + + strcpy(file, filename); + + /* check if we can read from this file (it exists and read permission) */ + if ( access(file, 04) != 0 ) + { + /* Try with .bmp extention */ + strcat(file, ".bmp"); + if ( access(file, 04) != 0 ) + { + free(pixmap); + return NULL; + } + } + + /* Try to load the bitmap from file */ + if ( !_load_bitmap_file(file, handle, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height) ) + { + free(pixmap); + return NULL; + } + + /* Success fill in other values */ + pixmap->handle = handle; + pixmap->transcolor = DW_CLR_DEFAULT; + + return pixmap; +} + +/* + * Creates a pixmap from memory. + * Parameters: + * handle: Window handle the pixmap is associated with. + * data: Source of the image data + * (BMP on OS/2 or Windows, XPM on Unix) + * le: length of data + * Returns: + * A handle to a pixmap or NULL on failure. + */ +HPIXMAP API dw_pixmap_new_from_data(HWND handle, char *data, int len) +{ + HPIXMAP pixmap; + char *file; + FILE *fp; + + if ( !(pixmap = calloc(1,sizeof(struct _hpixmap))) ) + return NULL; + + file = tmpnam( NULL ); + if ( file != NULL ) + { + fp = fopen( file, "wb" ); + if ( fp != NULL ) + { + fwrite( data, 1, len, fp ); + fclose( fp ); + if ( len > 1 && data[0] == 'B' && data[1] == 'M' ) /* first 2 chars of data is BM, then its a BMP */ + { + /* Try to load the bitmap from file */ + if ( !_load_bitmap_file(file, handle, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height) ) + { + free(pixmap); + return NULL; + } + } + else /* otherwise its assumed to be an ico */ + { + /* con't use ICO ? */ + unlink( file ); + return NULL; + } + } + else + { + unlink( file ); + return NULL; + } + unlink( file ); + } + + /* Success fill in other values */ + pixmap->handle = handle; + pixmap->transcolor = DW_CLR_DEFAULT; + + return pixmap; +} + +/* + * Creates a bitmap mask for rendering bitmaps with transparent backgrounds + */ +void API dw_pixmap_set_transparent_color( HPIXMAP pixmap, ULONG color ) +{ + if ( pixmap ) + { + pixmap->transcolor = _internal_color(color); + } +} + +/* + * Creates a pixmap from internal resource graphic specified by id. + * Parameters: + * handle: Window handle the pixmap is associated with. + * id: Resource ID associated with requested pixmap. + * Returns: + * A handle to a pixmap or NULL on failure. + */ +HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id) +{ + BITMAPINFOHEADER bmih; + SIZEL sizl = { 0, 0 }; + HPIXMAP pixmap; + HDC hdc; + HPS hps; + ULONG ulFlags; + + if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) + return NULL; + + hps = WinGetPS(handle); + + hdc = GpiQueryDevice(hps); + ulFlags = GpiQueryPS(hps, &sizl); + + pixmap->hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc); + pixmap->hps = GpiCreatePS (dwhab, pixmap->hdc, &sizl, ulFlags | GPIA_ASSOC); + + pixmap->hbm = GpiLoadBitmap(pixmap->hps, NULLHANDLE, id, 0, 0); + + GpiQueryBitmapParameters(pixmap->hbm, &bmih); + + GpiSetBitmap(pixmap->hps, pixmap->hbm); + + pixmap->width = bmih.cx; pixmap->height = bmih.cy; + pixmap->transcolor = DW_CLR_DEFAULT; + + WinReleasePS(hps); + + return pixmap; +} + +/* + * Sets the font used by a specified pixmap. + * Normally the pixmap font is obtained from the associated window handle. + * However this can be used to override that, or for pixmaps with no window. + * Parameters: + * pixmap: Handle to a pixmap returned by dw_pixmap_new() or + * passed to the application via a callback. + * fontname: Name and size of the font in the form "size.fontname" + * Returns: + * DW_ERROR_NONE on success and DW_ERROR_GENERAL on failure. + */ +int API dw_pixmap_set_font(HPIXMAP pixmap, char *fontname) +{ + if(pixmap && fontname && *fontname) + { + if(!pixmap->font) + pixmap->font = WinCreateWindow(HWND_OBJECT, WC_FRAME, NULL, 0,0,0,1,1, NULLHANDLE, HWND_TOP,0, NULL, NULL); + WinSetPresParam(pixmap->font, PP_FONTNAMESIZE, strlen(fontname)+1, fontname); + return DW_ERROR_NONE; + } + return DW_ERROR_GENERAL; +} + +/* + * Destroys an allocated pixmap. + * Parameters: + * pixmap: Handle to a pixmap returned by + * dw_pixmap_new.. + */ +void API dw_pixmap_destroy(HPIXMAP pixmap) +{ + if(pixmap->font) + WinDestroyWindow(pixmap->font); + GpiSetBitmap(pixmap->hps, NULLHANDLE); + GpiDeleteBitmap(pixmap->hbm); + GpiAssociate(pixmap->hps, NULLHANDLE); + GpiDestroyPS(pixmap->hps); + DevCloseDC(pixmap->hdc); + free(pixmap); +} + +/* + * Copies from one item to another. + * Parameters: + * dest: Destination window handle. + * destp: Destination pixmap. (choose only one). + * xdest: X coordinate of destination. + * ydest: Y coordinate of destination. + * width: Width of area to copy. + * height: Height of area to copy. + * src: Source window handle. + * srcp: Source pixmap. (choose only one). + * xsrc: X coordinate of source. + * ysrc: Y coordinate of source. + */ +void API dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc) +{ + dw_pixmap_stretch_bitblt(dest, destp, xdest, ydest, width, height, src, srcp, xsrc, ysrc, -1, -1); +} + +/* + * Copies from one surface to another allowing for stretching. + * Parameters: + * dest: Destination window handle. + * destp: Destination pixmap. (choose only one). + * xdest: X coordinate of destination. + * ydest: Y coordinate of destination. + * width: Width of the target area. + * height: Height of the target area. + * src: Source window handle. + * srcp: Source pixmap. (choose only one). + * xsrc: X coordinate of source. + * ysrc: Y coordinate of source. + * srcwidth: Width of area to copy. + * srcheight: Height of area to copy. + * Returns: + * DW_ERROR_NONE on success and DW_ERROR_GENERAL on failure. + */ +int API dw_pixmap_stretch_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc, int srcwidth, int srcheight) +{ + HPS hpsdest; + HPS hpssrc; + POINTL ptl[4]; + int dheight, sheight; + int count = 3; + + /* Do some sanity checks */ + if((srcheight == -1 || srcwidth == -1) && srcheight != srcwidth) + return DW_ERROR_GENERAL; + + if(dest) + { + hpsdest = WinGetPS(dest); + dheight = _get_height(dest); + } + else if(destp) + { + hpsdest = destp->hps; + dheight = destp->height; + } + else + return DW_ERROR_GENERAL; + + if(src) + { + hpssrc = WinGetPS(src); + sheight = _get_height(src); + } + else if(srcp) + { + hpssrc = srcp->hps; + sheight = srcp->height; + } + else + { + if(!destp) + WinReleasePS(hpsdest); + return DW_ERROR_GENERAL; + } + + ptl[0].x = xdest; + ptl[0].y = dheight - (ydest + height); + ptl[1].x = xdest + width; + ptl[1].y = dheight - ydest; + ptl[2].x = xsrc; + ptl[2].y = sheight - (ysrc + (srcheight != -1 ? srcheight : height)); + if(srcwidth != -1 && srcheight != -1) + { + count = 4; + ptl[3].x = xsrc + srcwidth; + ptl[3].y = sheight - ysrc; + } + + /* Handle transparency if requested */ + if(srcp && srcp->transcolor != DW_CLR_DEFAULT) + { + IMAGEBUNDLE newIb, oldIb; + /* Transparent color is put into the background color */ + GpiSetBackColor(hpsdest, srcp->transcolor); + GpiQueryAttrs(hpsdest, PRIM_IMAGE, IBB_BACK_MIX_MODE, (PBUNDLE)&oldIb); + newIb.usBackMixMode = BM_SRCTRANSPARENT; + GpiSetAttrs(hpsdest, PRIM_IMAGE, IBB_BACK_MIX_MODE, 0, (PBUNDLE)&newIb); + GpiBitBlt(hpsdest, hpssrc, count, ptl, ROP_SRCCOPY, BBO_IGNORE); + GpiSetAttrs(hpsdest, PRIM_IMAGE, IBB_BACK_MIX_MODE, 0, (PBUNDLE)&oldIb); + } + else + { + /* Otherwise use the regular BitBlt call */ + GpiBitBlt(hpsdest, hpssrc, count, ptl, ROP_SRCCOPY, BBO_IGNORE); + } + + if(!destp) + WinReleasePS(hpsdest); + if(!srcp) + WinReleasePS(hpssrc); + return DW_ERROR_NONE; +} + +/* Run DosBeep() in a separate thread so it doesn't block */ +void _beepthread(void *data) +{ + int *info = (int *)data; + + if(data) + { + DosBeep(info[0], info[1]); + free(data); + } +} + +/* + * Emits a beep. + * Parameters: + * freq: Frequency. + * dur: Duration. + */ +void API dw_beep(int freq, int dur) +{ + int *info = malloc(sizeof(int) * 2); + + if(info) + { + info[0] = freq; + info[1] = dur; + + _beginthread(_beepthread, NULL, 100, (void *)info); + } +} + +/* Open a shared library and return a handle. + * Parameters: + * name: Base name of the shared library. + * handle: Pointer to a module handle, + * will be filled in with the handle. + */ +int API dw_module_load(char *name, HMOD *handle) +{ + char objnamebuf[300] = ""; + + return DosLoadModule(objnamebuf, sizeof(objnamebuf), name, handle); +} + +/* Queries the address of a symbol within open handle. + * Parameters: + * handle: Module handle returned by dw_module_load() + * name: Name of the symbol you want the address of. + * func: A pointer to a function pointer, to obtain + * the address. + */ +int API dw_module_symbol(HMOD handle, char *name, void**func) +{ + return DosQueryProcAddr(handle, 0, name, (PFN*)func); +} + +/* Frees the shared library previously opened. + * Parameters: + * handle: Module handle returned by dw_module_load() + */ +int API dw_module_close(HMOD handle) +{ + DosFreeModule(handle); + return 0; +} + +/* + * Returns the handle to an unnamed mutex semaphore. + */ +HMTX API dw_mutex_new(void) +{ + HMTX mutex; + + DosCreateMutexSem(NULL, &mutex, 0, FALSE); + return mutex; +} + +/* + * Closes a semaphore created by dw_mutex_new(). + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + */ +void API dw_mutex_close(HMTX mutex) +{ + DosCloseMutexSem(mutex); +} + +/* + * Tries to gain access to the semaphore, if it can't it blocks. + * If we are in a callback we must keep the message loop running + * while blocking. + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + */ +void API dw_mutex_lock(HMTX mutex) +{ + if(_dwtid == dw_thread_id()) + { + int rc = DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN); + + while(rc == ERROR_TIMEOUT) + { + dw_main_sleep(10); + rc = DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN); + } + } + else + DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT); +} + +/* + * Tries to gain access to the semaphore. + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + * Returns: + * DW_ERROR_NONE on success, DW_ERROR_TIMEOUT if it is already locked. + */ +int API dw_mutex_trylock(HMTX mutex) +{ + if(DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR) + return DW_ERROR_NONE; + return DW_ERROR_TIMEOUT; +} + +/* + * Reliquishes the access to the semaphore. + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + */ +void API dw_mutex_unlock(HMTX mutex) +{ + DosReleaseMutexSem(mutex); +} + +/* + * Returns the handle to an unnamed event semaphore. + */ +HEV API dw_event_new(void) +{ + HEV blah; + + if(DosCreateEventSem (NULL, &blah, 0L, FALSE)) + return 0; + + return blah; +} + +/* + * Resets a semaphore created by dw_event_new(). + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int API dw_event_reset(HEV eve) +{ + ULONG count; + + if(DosResetEventSem(eve, &count)) + return DW_ERROR_GENERAL; + return DW_ERROR_NONE; +} + +/* + * Posts a semaphore created by dw_event_new(). Causing all threads + * waiting on this event in dw_event_wait to continue. + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int API dw_event_post(HEV eve) +{ + if(DosPostEventSem(eve)) + return DW_ERROR_GENERAL; + return DW_ERROR_NONE; +} + + +/* + * Waits on a semaphore created by dw_event_new(), until the + * event gets posted or until the timeout expires. + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int API dw_event_wait(HEV eve, unsigned long timeout) +{ + int rc = DosWaitEventSem(eve, timeout); + if(!rc) + return DW_ERROR_NONE; + if(rc == ERROR_TIMEOUT) + return DW_ERROR_TIMEOUT; + return DW_ERROR_GENERAL; +} + +/* + * Closes a semaphore created by dw_event_new(). + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int API dw_event_close(HEV *eve) +{ + if(!eve || ~DosCloseEventSem(*eve)) + return DW_ERROR_GENERAL; + return DW_ERROR_NONE; +} + +/* Create a named event semaphore which can be + * opened from other processes. + * Parameters: + * eve: Pointer to an event handle to receive handle. + * name: Name given to semaphore which can be opened + * by other processes. + */ +HEV API dw_named_event_new(char *name) +{ + char *semname = malloc(strlen(name)+8); + HEV ev = 0; + + if(!semname) + return 0; + + strcpy(semname, "\\sem32\\"); + strcat(semname, name); + + DosCreateEventSem(semname, &ev, 0L, FALSE); + + free(semname); + return ev; +} + +/* Open an already existing named event semaphore. + * Parameters: + * eve: Pointer to an event handle to receive handle. + * name: Name given to semaphore which can be opened + * by other processes. + */ +HEV API dw_named_event_get(char *name) +{ + char *semname = malloc(strlen(name)+8); + HEV ev; + + if(!semname) + return 0; + + strcpy(semname, "\\sem32\\"); + strcat(semname, name); + + DosOpenEventSem(semname, &ev); + + free(semname); + return ev; +} + +/* Resets the event semaphore so threads who call wait + * on this semaphore will block. + * Parameters: + * eve: Handle to the semaphore obtained by + * an open or create call. + */ +int API dw_named_event_reset(HEV eve) +{ + ULONG count; + + return DosResetEventSem(eve, &count); +} + +/* Sets the posted state of an event semaphore, any threads + * waiting on the semaphore will no longer block. + * Parameters: + * eve: Handle to the semaphore obtained by + * an open or create call. + */ +int API dw_named_event_post(HEV eve) +{ + return DosPostEventSem(eve); +} + + +/* Waits on the specified semaphore until it becomes + * posted, or returns immediately if it already is posted. + * Parameters: + * eve: Handle to the semaphore obtained by + * an open or create call. + * timeout: Number of milliseconds before timing out + * or -1 if indefinite. + */ +int API dw_named_event_wait(HEV eve, unsigned long timeout) +{ + int rc; + + rc = DosWaitEventSem(eve, timeout); + switch (rc) + { + case ERROR_INVALID_HANDLE: + rc = DW_ERROR_NON_INIT; + break; + case ERROR_NOT_ENOUGH_MEMORY: + rc = DW_ERROR_NO_MEM; + break; + case ERROR_INTERRUPT: + rc = DW_ERROR_INTERRUPT; + break; + case ERROR_TIMEOUT: + rc = DW_ERROR_TIMEOUT; + break; + } + + return rc; +} + +/* Release this semaphore, if there are no more open + * handles on this semaphore the semaphore will be destroyed. + * Parameters: + * eve: Handle to the semaphore obtained by + * an open or create call. + */ +int API dw_named_event_close(HEV eve) +{ + int rc; + + rc = DosCloseEventSem(eve); + switch (rc) + { + case ERROR_INVALID_HANDLE: + rc = DW_ERROR_NON_INIT; + break; + + case ERROR_SEM_BUSY: + rc = DW_ERROR_INTERRUPT; + break; + } + + return rc; +} + +/* + * Allocates a shared memory region with a name. + * Parameters: + * handle: A pointer to receive a SHM identifier. + * dest: A pointer to a pointer to receive the memory address. + * size: Size in bytes of the shared memory region to allocate. + * name: A string pointer to a unique memory name. + */ +HSHM API dw_named_memory_new(void **dest, int size, char *name) +{ + char namebuf[1024]; + + sprintf(namebuf, "\\sharemem\\%s", name); + + if(DosAllocSharedMem((void *)dest, namebuf, size, PAG_COMMIT | PAG_WRITE | PAG_READ) != NO_ERROR) + return 0; + + return 1; +} + +/* + * Aquires shared memory region with a name. + * Parameters: + * dest: A pointer to a pointer to receive the memory address. + * size: Size in bytes of the shared memory region to requested. + * name: A string pointer to a unique memory name. + */ +HSHM API dw_named_memory_get(void **dest, int size, char *name) +{ + char namebuf[1024]; + + size = size; + sprintf(namebuf, "\\sharemem\\%s", name); + + if(DosGetNamedSharedMem((void *)dest, namebuf, PAG_READ | PAG_WRITE) != NO_ERROR) + return 0; + + return 1; +} + +/* + * Frees a shared memory region previously allocated. + * Parameters: + * handle: Handle obtained from DB_named_memory_allocate. + * ptr: The memory address aquired with DB_named_memory_allocate. + */ +int API dw_named_memory_free(HSHM handle, void *ptr) +{ + handle = handle; + + if(DosFreeMem(ptr) != NO_ERROR) + return -1; + return 0; +} + +/* + * Encapsulate the message queues on OS/2. + */ +void _dwthreadstart(void *data) +{ + HAB thishab = WinInitialize(0); + HMQ thishmq = WinCreateMsgQueue(dwhab, 0); + void (* API threadfunc)(void *) = NULL; + void **tmp = (void **)data; + + threadfunc = (void (* API)(void *))tmp[0]; + threadfunc(tmp[1]); + + free(tmp); + + WinDestroyMsgQueue(thishmq); + WinTerminate(thishab); +} + +/* + * Creates a new thread with a starting point of func. + * Parameters: + * func: Function which will be run in the new thread. + * data: Parameter(s) passed to the function. + * stack: Stack size of new thread (OS/2 and Windows only). + */ +DWTID API dw_thread_new(void *func, void *data, int stack) +{ + void **tmp = malloc(sizeof(void *) * 2); + + tmp[0] = func; + tmp[1] = data; + + return (DWTID)_beginthread((void (*)(void *))_dwthreadstart, NULL, stack, (void *)tmp); +} + +/* + * Ends execution of current thread immediately. + */ +void API dw_thread_end(void) +{ + _endthread(); +} + +/* + * Returns the current thread's ID. + */ +DWTID API dw_thread_id(void) +{ + return (DWTID)_threadid; +} + +/* + * 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) +{ + /* Destroy the menu message window */ + dw_window_destroy(hwndApp); + + /* In case we are in a signal handler, don't + * try to free memory that could possibly be + * free()'d by the runtime already. + */ + Root = NULL; + + DosFreeModule(wpconfig); + exit(exitcode); +} + +/* + * Creates a splitbar window (widget) with given parameters. + * Parameters: + * type: Value can be DW_VERT or DW_HORZ. + * topleft: Handle to the window to be top or left. + * bottomright: Handle to the window to be bottom or right. + * Returns: + * A handle to a splitbar window or NULL on failure. + */ +HWND API dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id) +{ + HWND tmp = WinCreateWindow(HWND_OBJECT, + SplitbarClassName, + NULL, + WS_VISIBLE | WS_CLIPCHILDREN, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + if(tmp) + { + HWND tmpbox = dw_box_new(DW_VERT, 0); + float *percent = malloc(sizeof(float)); + + dw_box_pack_start(tmpbox, topleft, 1, 1, TRUE, TRUE, 0); + WinSetParent(tmpbox, tmp, FALSE); + dw_window_set_data(tmp, "_dw_topleft", (void *)tmpbox); + + tmpbox = dw_box_new(DW_VERT, 0); + dw_box_pack_start(tmpbox, bottomright, 1, 1, TRUE, TRUE, 0); + WinSetParent(tmpbox, tmp, FALSE); + *percent = 50.0; + dw_window_set_data(tmp, "_dw_bottomright", (void *)tmpbox); + dw_window_set_data(tmp, "_dw_percent", (void *)percent); + dw_window_set_data(tmp, "_dw_type", (void *)type); + } + return tmp; +} + +/* + * Sets the position of a splitbar (pecentage). + * Parameters: + * handle: The handle to the splitbar returned by dw_splitbar_new(). + */ +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; + + if(mypercent) + *mypercent = percent; + + dw_window_get_pos_size(handle, NULL, NULL, &width, &height); + + _handle_splitbar_resize(handle, percent, type, width, height); +} + +/* + * Gets the position of a splitbar (pecentage). + * Parameters: + * handle: The handle to the splitbar returned by dw_splitbar_new(). + */ +float API dw_splitbar_get(HWND handle) +{ + float *percent = (float *)dw_window_get_data(handle, "_dw_percent"); + + if(percent) + return *percent; + return 0.0; +} + +/* The following two functions graciously contributed by Peter Nielsen. */ +static ULONG _ParseBuildLevel (char* pchBuffer, ULONG ulSize) { + char* pchStart = pchBuffer; + char* pchEnd = pchStart + ulSize - 2; + + while (pchEnd >= pchStart) + { + if ((pchEnd[0] == '#') && (pchEnd[1] == '@')) + { + *pchEnd-- = '\0'; + while (pchEnd >= pchStart) + { + if ((pchEnd[0] == '@') && (pchEnd[1] == '#')) + { + ULONG ulMajor = 0; + ULONG ulMinor = 0; + + char* pch = pchEnd + 2; + while (!isdigit ((int)*pch) && *pch) + pch++; + + while (isdigit ((int)*pch)) + ulMajor = ulMajor * 10 + *pch++ - '0'; + + if (*pch == '.') + { + while (isdigit ((int)*++pch)) + ulMinor = ulMinor * 10 + *pch - '0'; + } + return ((ulMajor << 16) | ulMinor); + } + pchEnd--; + } + } + pchEnd--; + } + return (0); +} + +ULONG _GetSystemBuildLevel(void) { + /* The build level info is normally available in the end of the OS2KRNL file. However, this is not the case in some beta versions of OS/2. + * We first try to find the info in the 256 last bytes of the file. If that fails, we load the entire file and search it completely. + */ + ULONG ulBootDrive = 0; + ULONG ulBuild = 0; + if (DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive, sizeof (ulBootDrive)) == NO_ERROR) + { + char achFileName[11] = "C:\\OS2KRNL"; + HFILE hfile; + ULONG ulResult; + + achFileName[0] = (char)('A'+ulBootDrive-1); + + if (DosOpen (achFileName, &hfile, &ulResult, 0, 0, OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL) == NO_ERROR) + { + ULONG ulFileSize = 0; + if (DosSetFilePtr (hfile, 0, FILE_END, &ulFileSize) == NO_ERROR) + { + const ULONG ulFirstTry = min (256, ulFileSize); + if (DosSetFilePtr (hfile, -(LONG)ulFirstTry, FILE_END, &ulResult) == NO_ERROR) + { + char *pchBuffer = malloc(ulFirstTry); + if (DosRead (hfile, pchBuffer, ulFirstTry, &ulResult) == NO_ERROR) + { + ulBuild = _ParseBuildLevel (pchBuffer, ulFirstTry); + if (ulBuild == 0) + { + if (DosSetFilePtr (hfile, 0, FILE_BEGIN, &ulResult) == NO_ERROR) + { + free(pchBuffer); + pchBuffer = malloc(ulFileSize); + + if (DosRead (hfile, pchBuffer, ulFileSize, &ulResult) == NO_ERROR) + ulBuild = _ParseBuildLevel (pchBuffer, ulFileSize); + } + } + } + free(pchBuffer); + } + } + DosClose (hfile); + } + } + return (ulBuild); +} + +/* + * Sets the default focus item for a window/dialog. + * Parameters: + * window: Toplevel window or dialog. + * defaultitem: Handle to the dialog item to be default. + */ +void API dw_window_default(HWND window, HWND defaultitem) +{ + Box *thisbox = NULL; + HWND box; + + box = WinWindowFromID(window, FID_CLIENT); + if(box) + thisbox = WinQueryWindowPtr(box, QWP_USER); + + if(thisbox) + thisbox->defaultitem = defaultitem; +} + +/* + * Sets window to click the default dialog item when an ENTER is pressed. + * Parameters: + * window: Window (widget) to look for the ENTER press. + * next: Window (widget) to move to next (or click) + */ +void API dw_window_click_default(HWND window, HWND next) +{ + WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER); + + if(blah) + blah->clickdefault = next; +} + +/* + * Gets the contents of the default clipboard as text. + * Parameters: + * None. + * Returns: + * Pointer to an allocated string of text or NULL if clipboard empty or contents could not + * be converted to text. + */ +char *dw_clipboard_get_text() +{ + APIRET rc; + char *retbuf = NULL; + ULONG fmtInfo; + + WinOpenClipbrd(dwhab); + + rc = WinQueryClipbrdFmtInfo(dwhab, CF_TEXT, &fmtInfo); + if (rc) /* Text data in clipboard */ + { + PSZ pszClipText = (PSZ)WinQueryClipbrdData(dwhab, CF_TEXT); /* Query data handle */ + retbuf = strdup(pszClipText); + } + WinCloseClipbrd(dwhab); + return retbuf; +} + +/* + * Sets the contents of the default clipboard to the supplied text. + * Parameters: + * Text. + */ +void dw_clipboard_set_text( char *str, int len ) +{ + APIRET rc; + static PVOID shared; + + WinOpenClipbrd(dwhab); /* Open clipboard */ + WinEmptyClipbrd(dwhab); /* Empty clipboard */ + + /* Ok, clipboard wants giveable unnamed shared memory */ + + shared = NULL; + rc = DosAllocSharedMem(&shared, NULL, len, OBJ_GIVEABLE | PAG_COMMIT | PAG_READ | PAG_WRITE); + + if (rc == 0) + { + memcpy(shared, str, len); + + WinSetClipbrdData(dwhab, (ULONG)shared, CF_TEXT, CFI_POINTER); + } + + WinCloseClipbrd(dwhab); /* Close clipboard */ + return; +} + +/* + * Returns some information about the current operating environment. + * Parameters: + * env: Pointer to a DWEnv struct. + */ +void API dw_environment_query(DWEnv *env) +{ + ULONG Build; + + if(!env) + return; + + /* The default is OS/2 2.0 */ + strcpy(env->osName,"OS/2"); + env->MajorVersion = 2; + env->MinorVersion = 0; + + Build = _GetSystemBuildLevel(); + env->MinorBuild = Build & 0xFFFF; + env->MajorBuild = Build >> 16; + + if (aulBuffer[0] == 20) + { + int i = (unsigned int)aulBuffer[1]; + if (i > 20) + { + strcpy(env->osName,"Warp"); + env->MajorVersion = (int)i/10; + env->MinorVersion = i-(((int)i/10)*10); + } + else if (i == 10) + env->MinorVersion = 1; + } + strcpy(env->buildDate, __DATE__); + strcpy(env->buildTime, __TIME__); + env->DWMajorVersion = DW_MAJOR_VERSION; + env->DWMinorVersion = DW_MINOR_VERSION; +#ifdef VER_REV + env->DWSubVersion = VER_REV; +#else + env->DWSubVersion = DW_SUB_VERSION; +#endif +} + +/* The next few functions are support functions for the OS/2 folder browser */ +void _populate_directory(HWND tree, HTREEITEM parent, char *path) +{ + FILEFINDBUF3 ffbuf; + HTREEITEM item; + ULONG count = 1; + HDIR hdir = HDIR_CREATE; + + if(DosFindFirst(path, &hdir, FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_ARCHIVED | MUST_HAVE_DIRECTORY, + &ffbuf, sizeof(FILEFINDBUF3), &count, FIL_STANDARD) == NO_ERROR) + { + while(DosFindNext(hdir, &ffbuf, sizeof(FILEFINDBUF3), &count) == NO_ERROR) + { + if(strcmp(ffbuf.achName, ".") && strcmp(ffbuf.achName, "..")) + { + int len = strlen(path); + char *folder = malloc(len + ffbuf.cchName + 2); + HTREEITEM tempitem; + + strcpy(folder, path); + strcpy(&folder[len-1], ffbuf.achName); + + item = dw_tree_insert(tree, ffbuf.achName, WinLoadFileIcon(folder, TRUE), parent, (void *)parent); + tempitem = dw_tree_insert(tree, "", 0, item, 0); + dw_tree_item_set_data(tree, item, (void *)tempitem); + } + } + DosFindClose(hdir); + } +} + +void API _populate_tree_thread(void *data) +{ + HWND window = (HWND)data, tree = (HWND)dw_window_get_data(window, "_dw_tree"); + HMTX mtx = (HMTX)dw_window_get_data(window, "_dw_mutex"); + int drive; + HTREEITEM items[26]; + FSINFO volinfo; + + DosError(FERR_DISABLEHARDERR); + + dw_mutex_lock(mtx); + for(drive=0;drive<26;drive++) + { + if(DosQueryFSInfo(drive+1, FSIL_VOLSER,(PVOID)&volinfo, sizeof(FSINFO)) == NO_ERROR) + { + char folder[5] = "C:\\", name[9] = "Drive C:"; + HTREEITEM tempitem; + + folder[0] = name[6] = 'A' + drive; + + items[drive] = dw_tree_insert(tree, name, WinLoadFileIcon(folder, TRUE), NULL, 0); + tempitem = dw_tree_insert(tree, "", 0, items[drive], 0); + dw_tree_item_set_data(tree, items[drive], (void *)tempitem); + } + else + items[drive] = 0; + } + dw_mutex_unlock(mtx); + + DosError(FERR_ENABLEHARDERR); +} + +int DWSIGNAL _dw_ok_func(HWND window, void *data) +{ + DWDialog *dwwait = (DWDialog *)data; + HMTX mtx = (HMTX)dw_window_get_data((HWND)dwwait->data, "_dw_mutex"); + void *treedata; + + window = window; + if(!dwwait) + return FALSE; + + dw_mutex_lock(mtx); + treedata = dw_window_get_data((HWND)dwwait->data, "_dw_tree_selected"); + dw_mutex_close(mtx); + dw_window_destroy((HWND)dwwait->data); + dw_dialog_dismiss((DWDialog *)data, treedata); + return FALSE; +} + +int DWSIGNAL _dw_cancel_func(HWND window, void *data) +{ + DWDialog *dwwait = (DWDialog *)data; + HMTX mtx = (HMTX)dw_window_get_data((HWND)dwwait->data, "_dw_mutex"); + + window = window; + if(!dwwait) + return FALSE; + + dw_mutex_lock(mtx); + dw_mutex_close(mtx); + dw_window_destroy((HWND)dwwait->data); + dw_dialog_dismiss((DWDialog *)data, NULL); + return FALSE; +} + +char *_tree_folder(HWND tree, HTREEITEM item) +{ + char *folder=strdup(""); + HTREEITEM parent = item; + + while(parent) + { + char *temp, *text = dw_tree_get_title(tree, parent); + + if(text) + { + if(strncmp(text, "Drive ", 6) == 0) + text = &text[6]; + + temp = malloc(strlen(text) + strlen(folder) + 3); + strcpy(temp, text); + strcat(temp, "\\"); + strcat(temp, folder); + free(folder); + folder = temp; + } + parent = dw_tree_get_parent(tree, parent); + } + return folder; +} + +int DWSIGNAL _item_select(HWND window, HTREEITEM item, char *text, void *data, void *itemdata) +{ + DWDialog *dwwait = (DWDialog *)data; + char *treedata = (char *)dw_window_get_data((HWND)dwwait->data, "_dw_tree_selected"); + + text = text; itemdata = itemdata; + if(treedata) + free(treedata); + + treedata = _tree_folder(window, item); + dw_window_set_data((HWND)dwwait->data, "_dw_tree_selected", (void *)treedata); + + return FALSE; +} + +int DWSIGNAL _tree_expand(HWND window, HTREEITEM item, void *data) +{ + HTREEITEM tempitem = (HTREEITEM)dw_tree_item_get_data(window, item); + + data = data; + if(tempitem) + { + char *folder = _tree_folder(window, item); + + dw_tree_item_set_data(window, item, 0); + dw_tree_item_delete(window, tempitem); + + if(*folder) + { + strcat(folder, "*"); + _populate_directory(window, item, folder); + } + free(folder); + } + + return FALSE; +} + +/* + * Opens a file dialog and queries user selection. + * Parameters: + * title: Title bar text for dialog. + * defpath: The default path of the open dialog. + * ext: Default file extention. + * flags: DW_FILE_OPEN or DW_FILE_SAVE. + * Returns: + * NULL on error. A malloced buffer containing + * the file path on success. + * + */ +char * API dw_file_browse(char *title, char *defpath, char *ext, int flags) +{ + if(flags == DW_DIRECTORY_OPEN) + { + HWND window, hbox, vbox, tree, button; + DWDialog *dwwait; + HMTX mtx = dw_mutex_new(); + + window = dw_window_new( HWND_DESKTOP, title, FCF_SHELLPOSITION | FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX); + + vbox = dw_box_new(DW_VERT, 5); + + dw_box_pack_start(window, vbox, 0, 0, TRUE, TRUE, 0); + + tree = dw_tree_new(60); + + dw_box_pack_start(vbox, tree, 1, 1, TRUE, TRUE, 0); + dw_window_set_data(window, "_dw_mutex", (void *)mtx); + dw_window_set_data(window, "_dw_tree", (void *)tree); + + hbox = dw_box_new(DW_HORZ, 0); + + dw_box_pack_start(vbox, hbox, 0, 0, TRUE, FALSE, 0); + + dwwait = dw_dialog_new((void *)window); + + dw_signal_connect(tree, DW_SIGNAL_ITEM_SELECT, DW_SIGNAL_FUNC(_item_select), (void *)dwwait); + dw_signal_connect(tree, DW_SIGNAL_TREE_EXPAND, DW_SIGNAL_FUNC(_tree_expand), (void *)dwwait); + + button = dw_button_new("Ok", 1001L); + dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3); + dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_ok_func), (void *)dwwait); + + button = dw_button_new("Cancel", 1002L); + dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3); + dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_cancel_func), (void *)dwwait); + dw_signal_connect(window, DW_SIGNAL_DELETE, DW_SIGNAL_FUNC(_dw_cancel_func), (void *)dwwait); + + dw_window_set_size(window, 225, 300); + dw_window_show(window); + + dw_thread_new((void *)_populate_tree_thread, (void *)window, 0xff); + return (char *)dw_dialog_wait(dwwait); + } + else + { + FILEDLG fild = { 0 }; + HWND hwndFile; + int len; + struct stat buf; + + if(defpath) + { + if(DosQueryPathInfo(defpath, FIL_QUERYFULLNAME, fild.szFullFile, sizeof(fild.szFullFile))) + strcpy(fild.szFullFile, defpath); + }; + + len = strlen(fild.szFullFile); + + /* If we have a defpath */ + if(len) + { + /* Check to see if it exists */ + if(stat(fild.szFullFile, &buf) == 0) + { + /* If it is a directory... make sure there is a trailing \ */ + if(buf.st_mode & S_IFDIR) + { + if(fild.szFullFile[len-1] != '\\') + strcat(fild.szFullFile, "\\"); + /* Set len to 0 so the wildcard gets added below */ + len = 0; + } + } + } + + /* If we need a wildcard (defpath isn't a file) */ + if(!len) + { + /* Add a * to get all files... */ + strcat(fild.szFullFile, "*"); + + /* If an extension was requested... */ + if(ext) + { + /* Limit the results further */ + strcat(fild.szFullFile, "."); + strcat(fild.szFullFile, ext); + } + } + + /* Setup the structure */ + fild.cbSize = sizeof(FILEDLG); + fild.fl = FDS_CENTER | FDS_OPEN_DIALOG; + fild.pszTitle = title; + fild.pszOKButton = ((flags & DW_FILE_SAVE) ? "Save" : "Open"); + fild.pfnDlgProc = (PFNWP)WinDefFileDlgProc; + + hwndFile = WinFileDlg(HWND_DESKTOP, HWND_DESKTOP, &fild); + if(hwndFile) + { + switch(fild.lReturn) + { + case DID_OK: + return strdup(fild.szFullFile); + case DID_CANCEL: + return NULL; + } + } + } + return NULL; +} + +/* Internal function to set drive and directory */ +int _SetPath(char *path) +{ +#ifndef __WATCOMC__ + if(strlen(path) > 2) + { + if(path[1] == ':') + { + char drive = toupper(path[0]); + _chdrive((drive - 'A')+1); + } + } +#endif + return chdir(path); +} + +/* + * Execute and external program in a seperate session. + * Parameters: + * program: Program name with optional path. + * type: Either DW_EXEC_CON or DW_EXEC_GUI. + * params: An array of pointers to string arguements. + * Returns: + * -1 on error. + */ +int API dw_exec(char *program, int type, char **params) +{ + type = type; /* keep compiler happy */ + return spawnvp(P_NOWAIT, program, params); +} + +/* + * Loads a web browser pointed at the given URL. + * Parameters: + * url: Uniform resource locator. + */ +int API dw_browse(char *url) +{ + char *execargs[3], browser[1024], *olddir, *newurl = NULL; + int len, ret; + + olddir = _getcwd(NULL, 1024); + + PrfQueryProfileString(HINI_USERPROFILE, "WPURLDEFAULTSETTINGS", + "DefaultWorkingDir", NULL, browser, 1024); + + if(browser[0]) + _SetPath(browser); + + PrfQueryProfileString(HINI_USERPROFILE, "WPURLDEFAULTSETTINGS", + "DefaultBrowserExe", NULL, browser, 1024); + + len = strlen(browser) - strlen("explore.exe"); + + execargs[0] = browser; + execargs[1] = url; + execargs[2] = NULL; + + /* Special case for Web Explorer, it requires file:/// instead + * of file:// so I am handling it here. + */ + if(len > 0) + { + if(stricmp(&browser[len], "explore.exe") == 0 && stricmp(url, "file://") == 0) + { + int newlen, z; + newurl = malloc(strlen(url) + 2); + sprintf(newurl, "file:///%s", &url[7]); + newlen = strlen(newurl); + for(z=8;z<(newlen-8);z++) + { + if(newurl[z] == '|') + newurl[z] = ':'; + if(newurl[z] == '/') + newurl[z] = '\\'; + } + execargs[1] = newurl; + } + } + + ret = dw_exec(browser, DW_EXEC_GUI, execargs); + + if(olddir) + { + _SetPath(olddir); + free(olddir); + } + if(newurl) + free(newurl); + return ret; +} + +/* + * Causes the embedded HTML widget to take action. + * Parameters: + * handle: Handle to the window. + * action: One of the DW_HTML_* constants. + */ +void API dw_html_action(HWND handle, int action) +{ + handle = handle; + action = action; +} + +/* + * Render raw HTML code in the embedded HTML widget.. + * Parameters: + * handle: Handle to the window. + * string: String buffer containt HTML code to + * be rendered. + * Returns: + * 0 on success. + */ +int API dw_html_raw(HWND handle, char *string) +{ + handle = handle; + string = string; + return -1; +} + +/* + * Render file or web page in the embedded HTML widget.. + * Parameters: + * handle: Handle to the window. + * url: Universal Resource Locator of the web or + * file object to be rendered. + * Returns: + * 0 on success. + */ +int API dw_html_url(HWND handle, char *url) +{ + handle = handle; + url = url; + return -1; +} + +/* + * Create a new HTML window (widget) to be packed. + * Not available under OS/2, eCS + * Parameters: + * text: The default text to be in the entryfield widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_html_new(unsigned long id) +{ + id = id; + return dw_box_new(DW_HORZ, 0); +} + +typedef struct _dwprint +{ + HDC hdc; + char *printername; + int (* API drawfunc)(HPRINT, HPIXMAP, int, void *); + void *drawdata; + unsigned long flags; + unsigned int startpage, endpage; + char *jobname; +} DWPrint; + +/* Internal functions to handle the print dialog */ +int DWSIGNAL _dw_printer_cancel_func(HWND window, void *data) +{ + DWPrint *print = (DWPrint *)data; + DWDialog *dwwait = (DWDialog *)print->printername; + + window = (HWND)dwwait->data; + + dw_window_destroy(window); + dw_dialog_dismiss(dwwait, NULL); + return FALSE; +} + +int DWSIGNAL _dw_printer_ok_func(HWND window, void *data) +{ + DWPrint *print = (DWPrint *)data; + DWDialog *dwwait = (DWDialog *)print->printername; + HWND printerlist, startspin, endspin; + char *result = NULL; + + window = (HWND)dwwait->data; + printerlist = (HWND)dw_window_get_data(window, "_dw_list"); + startspin = (HWND)dw_window_get_data(window, "_dw_start_spin"); + endspin = (HWND)dw_window_get_data(window, "_dw_end_spin"); + if(printerlist) + { + char printername[32] = ""; + int selected = dw_listbox_selected(printerlist); + + /* Get the name of the selected printer */ + if(selected != DW_ERROR_UNKNOWN) + { + dw_listbox_get_text(printerlist, selected, printername, 32); + if(printername[0]) + print->printername = result = strdup(printername); + } + /* Get the start and end positions */ + print->startpage = (unsigned int)dw_spinbutton_get_pos(startspin); + print->endpage = (unsigned int)dw_spinbutton_get_pos(endspin); + + /* If the start is bigger than end... swap them */ + if(print->startpage > print->endpage) + { + print->endpage = print->startpage; + print->startpage = (unsigned int)dw_spinbutton_get_pos(endspin); + } + } + + dw_window_destroy(window); + dw_dialog_dismiss(dwwait, (void *)result); + return FALSE; +} + +/* Borrowed functions which should probably be rewritten */ +BOOL _ExtractLogAddress(char * LogAddress, char * DetailStr) +{ + char *p; + + p = DetailStr; + while(*p++ != ';'); /* Gets to first ';' and one char beyond */ + while(*p++ != ';'); /* Gets to second ';' and one char beyond */ + while(*p != ';') *LogAddress++ = *p++; + *LogAddress = '\0'; + return TRUE; +} + +BOOL _ExtractDriverName(char * DriverName, char * DetailStr) +{ + char *p; + + p = DetailStr; + while(*p++ != ';'); /* Gets to first ';' and one char beyond */ + while(*p != '.' && *p != ';' && *p != ',') + *DriverName++ = *p++; + *DriverName = '\0'; + return TRUE; +} + +/* EMX Doesn't seem to define this? */ +#ifndef NERR_BufTooSmall +#define NERR_BufTooSmall 2123 +#endif + +/* + * Creates a new print object. + * Parameters: + * jobname: Name of the print job to show in the queue. + * flags: Flags to initially configure the print object. + * pages: Number of pages to print. + * drawfunc: The pointer to the function to be used as the callback. + * drawdata: User data to be passed to the handler function. + * Returns: + * A handle to the print object or NULL on failure. + */ +HPRINT API dw_print_new(char *jobname, unsigned long flags, unsigned int pages, void *drawfunc, void *drawdata) +{ + char printername[32], tmpbuf[20]; + HWND window, hbox, vbox, printerlist, button, text; + DWDialog *dwwait; + DWPrint *print; + PVOID pBuf = NULL; + ULONG fsType = SPL_PR_QUEUE; + ULONG cbBuf, cRes, cTotal, cbNeeded; + SPLERR splerr = 0 ; + PPRINTERINFO pRes ; /* Check the default printer for now... want a printer list in the future */ + int cb = PrfQueryProfileString(HINI_PROFILE, "PM_SPOOLER", "PRINTER", "", printername, 32); + + if(!drawfunc || !(print = calloc(1, sizeof(DWPrint)))) + return NULL; + + print->drawfunc = drawfunc; + print->drawdata = drawdata; + print->jobname = jobname ? jobname : "Dynamic Windows Print Job"; + print->startpage = 1; + print->endpage = pages; + print->flags = flags; + + /* Check to see how much space we need for the printer list */ + splerr = SplEnumPrinter(NULL, 0, fsType, NULL, 0, &cRes, &cTotal, &cbNeeded ,NULL); + + if(splerr == ERROR_MORE_DATA || splerr == NERR_BufTooSmall) + { + /* Allocate memory for the buffer using the count of bytes that were returned in cbNeeded. */ + DosAllocMem(&pBuf, cbNeeded, PAG_READ|PAG_WRITE|PAG_COMMIT); + + /* Set count of bytes in buffer to value used to allocate buffer. */ + cbBuf = cbNeeded; + + /* Call function again with the correct buffer size. */ + splerr = SplEnumPrinter(NULL, 0, fsType, pBuf, cbBuf, &cRes, &cTotal, &cbNeeded, NULL); + } + + /* Make sure we got a valid result */ + if(cb > 2) + printername[cb-2] = '\0'; + else + printername[0] = '\0'; + + /* If we didnt' get a printer list or default printer abort */ + if(!cRes && !printername[0]) + { + /* Show an error and return failure */ + dw_messagebox("Printing", DW_MB_ERROR | DW_MB_OK, "No printers detected."); + free(print); + return NULL; + } + + /* Create the print dialog */ + window = dw_window_new(HWND_DESKTOP, "Choose Printer", FCF_SHELLPOSITION | FCF_TITLEBAR | FCF_DLGBORDER | FCF_CLOSEBUTTON | FCF_SYSMENU); + + vbox = dw_box_new(DW_VERT, 5); + + dw_box_pack_start(window, vbox, 0, 0, TRUE, TRUE, 0); + + printerlist = dw_listbox_new(0, FALSE); + dw_box_pack_start(vbox, printerlist, 1, 1, TRUE, TRUE, 0); + + /* If there are any returned structures in the buffer... */ + if(pBuf && cRes) + { + int count = 0; + + pRes = (PPRINTERINFO)pBuf ; + while(cRes--) + { + dw_listbox_append(printerlist, pRes[cRes].pszPrintDestinationName); + /* If this is the default printer... select it by default */ + if(strcmp(pRes[cRes].pszPrintDestinationName, printername) == 0) + dw_listbox_select(printerlist, count, TRUE); + count++; + } + } + else + { + /* Otherwise just add the default */ + dw_listbox_append(printerlist, printername); + dw_listbox_select(printerlist, 0, TRUE); + } + + /* Free any unneeded memory */ + if(pBuf) + DosFreeMem(pBuf); + + dw_window_set_data(window, "_dw_list", (void *)printerlist); + + /* Start spinbutton */ + hbox = dw_box_new(DW_HORZ, 0); + + dw_box_pack_start(vbox, hbox, 0, 0, TRUE, FALSE, 0); + + text = dw_text_new("Start page:", 0); + dw_window_set_style(text, DW_DT_VCENTER, DW_DT_VCENTER); + dw_box_pack_start(hbox, text, 70, 20, FALSE, FALSE, 3); + + button = dw_spinbutton_new("1", 0); + dw_spinbutton_set_limits(button, 1, pages); + dw_box_pack_start(hbox, button, 20, 20, TRUE, FALSE, 3); + dw_window_set_data(window, "_dw_start_spin", (void *)button); + + /* End spinbutton */ + hbox = dw_box_new(DW_HORZ, 0); + + dw_box_pack_start(vbox, hbox, 0, 0, TRUE, FALSE, 0); + + text = dw_text_new("End page:", 0); + dw_window_set_style(text, DW_DT_VCENTER, DW_DT_VCENTER); + dw_box_pack_start(hbox, text, 70, 20, FALSE, FALSE, 3); + + sprintf(tmpbuf, "%d", pages); + button = dw_spinbutton_new(tmpbuf, 0); + dw_spinbutton_set_limits(button, 1, pages); + dw_box_pack_start(hbox, button, 20, 20, TRUE, FALSE, 3); + dw_window_set_data(window, "_dw_end_spin", (void *)button); + + /* Ok and Cancel buttons */ + hbox = dw_box_new(DW_HORZ, 0); + + dw_box_pack_start(vbox, hbox, 0, 0, TRUE, FALSE, 0); + dw_box_pack_start(hbox, 0, 100, 1, TRUE, FALSE, 0); + + button = dw_button_new("Ok", 0); + dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3); + + dwwait = dw_dialog_new((void *)window); + /* Save it temporarily there until we need it */ + print->printername = (char *)dwwait; + + dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_printer_ok_func), (void *)print); + + button = dw_button_new("Cancel", 0); + dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3); + + dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_printer_cancel_func), (void *)print); + dw_signal_connect(window, DW_SIGNAL_DELETE, DW_SIGNAL_FUNC(_dw_printer_cancel_func), (void *)print); + + dw_window_set_size(window, 300, 400); + + dw_window_show(window); + + print->printername = dw_dialog_wait(dwwait); + + /* The user picked a printer */ + if(print->printername) + { + char PrintDetails[256]; + char DriverName[32]; + char LogAddress[32]; + DEVOPENSTRUC dop; + + /* Get the printer information string */ + cb = PrfQueryProfileString(HINI_PROFILE, "PM_SPOOLER_PRINTER", print->printername, "", PrintDetails, 256); + _ExtractLogAddress(LogAddress, PrintDetails); + _ExtractDriverName(DriverName, PrintDetails); + dop.pszDriverName = DriverName; + dop.pszLogAddress = LogAddress; + dop.pdriv = NULL; + dop.pszDataType = "PM_Q_STD"; + /* Attempt to open a device context and return a handle to it */ + print->hdc = DevOpenDC(dwhab, OD_QUEUED, "*", 4L, (PDEVOPENDATA) &dop, (HDC)NULL); + if(print->hdc) + return print; + } + /* The user canceled */ + if(print->printername) + free(print->printername); + free(print); + return NULL; +} + +/* + * Runs the print job, causing the draw page callbacks to fire. + * Parameters: + * print: Handle to the print object returned by dw_print_new(). + * flags: Flags to run the print job. + * Returns: + * DW_ERROR_UNKNOWN on error or DW_ERROR_NONE on success. + */ +int API dw_print_run(HPRINT print, unsigned long flags) +{ + DWPrint *p = print; + HPIXMAP pixmap; + int x, result = DW_ERROR_UNKNOWN; + SIZEL sizl = { 0, 0 }; + + if(!p) + return result; + + if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) + return result; + + /* Start the job */ + DevEscape(p->hdc, DEVESC_STARTDOC, strlen(p->jobname), p->jobname, NULL, NULL); + + pixmap->font = WinCreateWindow(HWND_OBJECT, WC_FRAME, NULL, 0,0,0,1,1, NULLHANDLE, HWND_TOP,0, NULL, NULL); + pixmap->hdc = p->hdc; + pixmap->hps = GpiCreatePS(dwhab, p->hdc, &sizl, PU_PELS | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC); + pixmap->transcolor = DW_RGB_TRANSPARENT; + pixmap->width = sizl.cx; + pixmap->height = sizl.cy; + dw_pixmap_set_font(pixmap, DefaultFont); + + /* Cycle through each page */ + for(x=p->startpage-1; x<p->endpage && p->drawfunc; x++) + { + p->drawfunc(print, pixmap, x, p->drawdata); + /* Next page */ + DevEscape(p->hdc, DEVESC_NEWFRAME, 0, NULL, NULL, NULL); + } + /* Signal that we are done */ + DevEscape(p->hdc, DEVESC_ENDDOC, 0, NULL, NULL, NULL); + /* Determine the completion code */ + if(p->drawfunc) + result = DW_ERROR_NONE; + /* Free memory */ + dw_pixmap_destroy(pixmap); + if(p->printername) + free(p->printername); + free(p); + return result; +} + +/* + * Cancels the print job, typically called from a draw page callback. + * Parameters: + * print: Handle to the print object returned by dw_print_new(). + */ +void API dw_print_cancel(HPRINT print) +{ + DWPrint *p = print; + + if(p) + p->drawfunc = NULL; +} + +/* + * Returns a pointer to a static buffer which containes the + * current user directory. Or the root directory (C:\ on + * OS/2 and Windows). + */ +char * API dw_user_dir(void) +{ + static char _user_dir[1024] = ""; + + if(!_user_dir[0]) + { + char *home = getenv("HOME"); + + if(home) + strcpy(_user_dir, home); + else + strcpy(_user_dir, "C:\\"); + } + return _user_dir; +} + +/* + * Call a function from the window (widget)'s context. + * Parameters: + * handle: Window handle of the widget. + * function: Function pointer to be called. + * data: Pointer to the data to be passed to the function. + */ +void API dw_window_function(HWND handle, void *function, void *data) +{ + WinSendMsg(handle, WM_USER, (MPARAM)function, (MPARAM)data); +} + +/* Functions for managing the user data lists that are associated with + * a given window handle. Used in dw_window_set_data() and + * dw_window_get_data(). + */ +UserData *_find_userdata(UserData **root, char *varname) +{ + UserData *tmp = *root; + + while(tmp) + { + if(stricmp(tmp->varname, varname) == 0) + return tmp; + tmp = tmp->next; + } + return NULL; +} + +int _new_userdata(UserData **root, char *varname, void *data) +{ + UserData *new = _find_userdata(root, varname); + + if(new) + { + new->data = data; + return TRUE; + } + else + { + new = malloc(sizeof(UserData)); + if(new) + { + new->varname = strdup(varname); + new->data = data; + + new->next = NULL; + + if (!*root) + *root = new; + else + { + UserData *prev = *root, *tmp = prev->next; + + while(tmp) + { + prev = tmp; + tmp = tmp->next; + } + prev->next = new; + } + return TRUE; + } + } + return FALSE; +} + +int _remove_userdata(UserData **root, char *varname, int all) +{ + UserData *prev = NULL, *tmp = *root; + + while(tmp) + { + if(all || stricmp(tmp->varname, varname) == 0) + { + if(!prev) + { + *root = tmp->next; + free(tmp->varname); + free(tmp); + if(!all) + return 0; + tmp = *root; + } + else + { + /* If all is true we should + * never get here. + */ + prev->next = tmp->next; + free(tmp->varname); + free(tmp); + return 0; + } + } + else + { + prev = tmp; + tmp = tmp->next; + } + } + return 0; +} + +/* + * Add a named user data item to a window handle. + * Parameters: + * window: Window handle of signal to be called back. + * dataname: A string pointer identifying which signal to be hooked. + * data: User data to be passed to the handler function. + */ +void API dw_window_set_data(HWND window, char *dataname, void *data) +{ + WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER); + + if(!blah) + { + if(!dataname) + return; + + blah = calloc(1, sizeof(WindowData)); + WinSetWindowPtr(window, QWP_USER, blah); + } + + if(data) + _new_userdata(&(blah->root), dataname, data); + else + { + if(dataname) + _remove_userdata(&(blah->root), dataname, FALSE); + else + _remove_userdata(&(blah->root), NULL, TRUE); + } +} + +/* + * Gets a named user data item to a window handle. + * Parameters: + * window: Window handle of signal to be called back. + * dataname: A string pointer identifying which signal to be hooked. + * data: User data to be passed to the handler function. + */ +void * API dw_window_get_data(HWND window, char *dataname) +{ + WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER); + + if(blah && blah->root && dataname) + { + UserData *ud = _find_userdata(&(blah->root), dataname); + if(ud) + return ud->data; + } + return NULL; +} + +/* + * Add a callback to a timer event. + * Parameters: + * interval: Milliseconds to delay between calls. + * sigfunc: The pointer to the function to be used as the callback. + * data: User data to be passed to the handler function. + * Returns: + * Timer ID for use with dw_timer_disconnect(), 0 on error. + */ +int API dw_timer_connect(int interval, void *sigfunc, void *data) +{ + if(sigfunc) + { + int timerid = WinStartTimer(dwhab, NULLHANDLE, 0, interval); + + if(timerid) + { + _new_signal(WM_TIMER, NULLHANDLE, timerid, sigfunc, data); + return timerid; + } + } + return 0; +} + +/* + * Removes timer callback. + * Parameters: + * id: Timer ID returned by dw_timer_connect(). + */ +void API dw_timer_disconnect(int id) +{ + SignalHandler *prev = NULL, *tmp = Root; + + /* 0 is an invalid timer ID */ + if(!id) + return; + + WinStopTimer(dwhab, NULLHANDLE, id); + + while(tmp) + { + if(tmp->id == id) + { + if(prev) + { + prev->next = tmp->next; + free(tmp); + tmp = prev->next; + } + else + { + Root = tmp->next; + free(tmp); + tmp = Root; + } + } + else + { + prev = tmp; + tmp = tmp->next; + } + } +} + +/* + * Add a callback to a window event. + * 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. + * data: User data to be passed to the handler function. + */ +void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data) +{ + ULONG message = 0, id = 0; + + if(window && signame && sigfunc) + { + if((message = _findsigmessage(signame)) != 0) + { + /* Handle special case of the menu item */ + if(message == WM_COMMAND && window < 65536) + { + char buffer[15]; + HWND owner; + + sprintf(buffer, "_dw_id%d", (int)window); + owner = (HWND)dw_window_get_data(hwndApp, buffer); + + /* Make sure there are no dupes from popups */ + dw_signal_disconnect_by_window(window); + + if(owner) + { + id = window; + window = owner; + } + } + _new_signal(message, window, id, sigfunc, data); + } + } +} + +/* + * Removes callbacks for a given window with given name. + * Parameters: + * window: Window handle of callback to be removed. + */ +void API dw_signal_disconnect_by_name(HWND window, char *signame) +{ + SignalHandler *prev = NULL, *tmp = Root; + ULONG message; + + if(!window || !signame || (message = _findsigmessage(signame)) == 0) + return; + + while(tmp) + { + if(((window < 65536 && tmp->id == window) || tmp->window == window) && tmp->message == message) + { + if(prev) + { + prev->next = tmp->next; + free(tmp); + tmp = prev->next; + } + else + { + Root = tmp->next; + free(tmp); + tmp = Root; + } + } + else + { + prev = tmp; + tmp = tmp->next; + } + } +} + +/* + * Removes all callbacks for a given window. + * Parameters: + * window: Window handle of callback to be removed. + */ +void API dw_signal_disconnect_by_window(HWND window) +{ + SignalHandler *prev = NULL, *tmp = Root; + + while(tmp) + { + if((window < 65536 && tmp->id == window) || tmp->window == window) + { + if(prev) + { + prev->next = tmp->next; + free(tmp); + tmp = prev->next; + } + else + { + Root = tmp->next; + free(tmp); + tmp = Root; + } + } + else + { + prev = tmp; + tmp = tmp->next; + } + } +} + +/* + * Removes all callbacks for a given window with specified data. + * Parameters: + * window: Window handle of callback to be removed. + * data: Pointer to the data to be compared against. + */ +void API dw_signal_disconnect_by_data(HWND window, void *data) +{ + SignalHandler *prev = NULL, *tmp = Root; + + while(tmp) + { + if(((window < 65536 && tmp->id == window) || tmp->window == window) && tmp->data == data) + { + if(prev) + { + prev->next = tmp->next; + free(tmp); + tmp = prev->next; + } + else + { + Root = tmp->next; + free(tmp); + tmp = Root; + } + } + else + { + prev = tmp; + tmp = tmp->next; + } + } +} + + + +/* + * Create a new static text window (widget) to be packed. + * Not available under OS/2, eCS + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_calendar_new(ULONG id) +{ + char *text = "dummy calendar"; + WindowData *blah = calloc(sizeof(WindowData), 1); + HWND tmp = WinCreateWindow(HWND_OBJECT, + WC_STATIC, + text, + WS_VISIBLE | SS_TEXT, + 0,0,2000,1000, + NULLHANDLE, + HWND_TOP, + id, + NULL, + NULL); + blah->oldproc = WinSubclassWindow(tmp, _textproc); + WinSetWindowPtr(tmp, QWP_USER, blah); + dw_window_set_font(tmp, DefaultFont); + dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY); + WinSetWindowText(tmp, text); + return tmp; +} + +/* + * The following are stubs + */ +void API dw_calendar_set_date( HWND window, unsigned int year, unsigned int month, unsigned int day ) +{ + char tmp[30]; + sprintf( tmp, "%4.4d-%2.2d-%2.2d", year, month, day); + WinSetWindowText(window, tmp); +} + +void API dw_calendar_get_date( HWND window, unsigned int *year, unsigned int *month, unsigned int *day ) +{ + window = window; + *year = *month = *day = 0; +}
--- a/packinst/packinst.c Fri Feb 18 09:04:25 2011 -0600 +++ b/packinst/packinst.c Sun Nov 13 07:22:43 2011 -0600 @@ -106,7 +106,7 @@ char entry[8096], entrydata[8096]; int z; - printf("Packinst- version 2.1 (c) 1999-2003 DBSoft\n\n"); + printf("Packinst- version 2.1 (c) 1999-2011 DBSoft\n\n"); if(argc!=2) { printf("Usage: Packinst <filename.cfg>\n");
--- a/rexx.c Fri Feb 18 09:04:25 2011 -0600 +++ b/rexx.c Sun Nov 13 07:22:43 2011 -0600 @@ -786,12 +786,12 @@ return 0; } -int EXPENTRY rexx_dw_window_set_usize(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr) +int EXPENTRY rexx_dw_window_set_size(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr) { if(ArgCount < 3) return 40; - dw_window_set_usize((HWND)atol(Args[0].strptr),atol(Args[1].strptr),atol(Args[2].strptr)); + dw_window_set_size((HWND)atol(Args[0].strptr),atol(Args[1].strptr),atol(Args[2].strptr)); Retstr->strlength = 0; return 0; @@ -901,12 +901,12 @@ return 0; } -int EXPENTRY rexx_dw_checkbox_query(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr) +int EXPENTRY rexx_dw_checkbox_get(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr) { if(ArgCount < 1) return 40; - sprintf(Retstr->strptr, "%lu", (ULONG)dw_checkbox_query((HWND)atol(Args[0].strptr))); + sprintf(Retstr->strptr, "%lu", (ULONG)dw_checkbox_get((HWND)atol(Args[0].strptr))); Retstr->strlength = strlen(Retstr->strptr); return 0; @@ -995,7 +995,7 @@ if(buffer) { point = dw_mle_import(hwndMLE, buffer, point); - dw_mle_set(hwndMLE, 0); + dw_mle_set_cursor(hwndMLE, 0); free(buffer); } @@ -1233,7 +1233,7 @@ checkbox = (HWND)atol(Args[0].strptr); - if(dw_checkbox_query(checkbox)) + if(dw_checkbox_get(checkbox)) strcpy(Retstr->strptr, "1"); else strcpy(Retstr->strptr, "0"); @@ -1378,7 +1378,7 @@ RexxRegisterFunctionExe("dw_listbox_select", &rexx_dw_listbox_select); RexxRegisterFunctionExe("dw_listbox_selected", &rexx_dw_listbox_selected); RexxRegisterFunctionExe("dw_window_set_pos", &rexx_dw_window_set_pos); - RexxRegisterFunctionExe("dw_window_set_usize", &rexx_dw_window_set_usize); + RexxRegisterFunctionExe("dw_window_set_size", &rexx_dw_window_set_size); RexxRegisterFunctionExe("dw_window_set_pos_size", &rexx_dw_window_set_pos_size); RexxRegisterFunctionExe("dw_window_set_style", &rexx_dw_window_set_style); RexxRegisterFunctionExe("dw_window_set_icon", &rexx_dw_window_set_icon); @@ -1386,7 +1386,7 @@ RexxRegisterFunctionExe("dw_window_set_text", &rexx_dw_window_set_text); RexxRegisterFunctionExe("dw_window_enable", &rexx_dw_window_enable); RexxRegisterFunctionExe("dw_window_disable", &rexx_dw_window_disable); - RexxRegisterFunctionExe("dw_checkbox_query", &rexx_dw_checkbox_query); + RexxRegisterFunctionExe("dw_checkbox_get", &rexx_dw_checkbox_get); RexxRegisterFunctionExe("dw_checkbox_set", &rexx_dw_checkbox_set); RexxRegisterFunctionExe("dw_screen_width", &rexx_dw_screen_width); RexxRegisterFunctionExe("dw_screen_height", &rexx_dw_screen_height); @@ -1449,7 +1449,7 @@ RexxDeregisterFunction("dw_listbox_select"); RexxDeregisterFunction("dw_listbox_selected"); RexxDeregisterFunction("dw_window_set_pos"); - RexxDeregisterFunction("dw_window_set_usize"); + RexxDeregisterFunction("dw_window_set_size"); RexxDeregisterFunction("dw_window_set_pos_size"); RexxDeregisterFunction("dw_window_set_style"); RexxDeregisterFunction("dw_window_set_icon"); @@ -1458,7 +1458,7 @@ RexxDeregisterFunction("dw_window_enable"); RexxDeregisterFunction("dw_window_disable"); RexxDeregisterFunction("dw_checkbox_set"); - RexxDeregisterFunction("dw_checkbox_query"); + RexxDeregisterFunction("dw_checkbox_get"); RexxDeregisterFunction("dw_screen_width"); RexxDeregisterFunction("dw_screen_height"); RexxDeregisterFunction("dw_yesno");
--- a/win/dw.c Fri Feb 18 09:04:25 2011 -0600 +++ b/win/dw.c Sun Nov 13 07:22:43 2011 -0600 @@ -1,8516 +1,10985 @@ -/* -/* - * Dynamic Windows: - * A GTK like implementation of the Win32 GUI - * - * (C) 2000-2003 Brian Smith <dbsoft@technologist.com> - * (C) 2003 Mark Hessling <m.hessling@qut.edu.au> - * - */ -#define _WIN32_IE 0x0500 -#ifdef WINNT_COMPAT -#define WINVER 0x400 -#else -#define WINVER 0x500 -#endif -#include <windows.h> -#include <windowsx.h> -#include <commctrl.h> -#include <shlwapi.h> -#include <shlobj.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <process.h> -#include <time.h> -#include "dw.h" - -HWND popup = (HWND)NULL, hwndBubble = (HWND)NULL, hwndBubbleLast, DW_HWND_OBJECT = (HWND)NULL; - -HINSTANCE DWInstance = NULL; - -DWORD dwVersion = 0, dwComctlVer = 0; -DWTID _dwtid = -1; - -#define PACKVERSION(major,minor) MAKELONG(minor,major) - -#define IS_IE5PLUS (dwComctlVer >= PACKVERSION(5,80)) - -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -int main(int argc, char *argv[]); - -#define ICON_INDEX_LIMIT 200 -HICON lookup[200]; -HIMAGELIST hSmall = 0, hLarge = 0; - -/* Special flag used for internal tracking */ -#define DW_CFA_RESERVED (1 << 30) - -#define THREAD_LIMIT 128 -COLORREF _foreground[THREAD_LIMIT]; -COLORREF _background[THREAD_LIMIT]; -HPEN _hPen[THREAD_LIMIT]; -HBRUSH _hBrush[THREAD_LIMIT]; - -BYTE _red[] = { 0x00, 0xbb, 0x00, 0xaa, 0x00, 0xbb, 0x00, 0xaa, 0x77, - 0xff, 0x00, 0xee, 0x00, 0xff, 0x00, 0xff, 0xaa, 0x00 }; -BYTE _green[] = { 0x00, 0x00, 0xbb, 0xaa, 0x00, 0x00, 0xbb, 0xaa, 0x77, - 0x00, 0xff, 0xee, 0x00, 0x00, 0xee, 0xff, 0xaa, 0x00 }; -BYTE _blue[] = { 0x00, 0x00, 0x00, 0x00, 0xcc, 0xbb, 0xbb, 0xaa, 0x77, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xee, 0xff, 0xaa, 0x00}; - -HBRUSH _colors[18]; - - -void _resize_notebook_page(HWND handle, int pageid); -void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y); -int _lookup_icon(HWND handle, HICON hicon, int type); -HFONT _acquire_font(HWND handle, char *fontname); - -typedef struct _sighandler -{ - struct _sighandler *next; - ULONG message; - HWND window; - int id; - void *signalfunction; - void *data; - -} SignalHandler; - -SignalHandler *Root = NULL; -int _index; - -typedef struct -{ - ULONG message; - char name[30]; - -} SignalList; - -static int in_checkbox_handler = 0; - -/* List of signals and their equivilent Win32 message */ -#define SIGNALMAX 17 - -SignalList SignalTranslate[SIGNALMAX] = { - { WM_SIZE, DW_SIGNAL_CONFIGURE }, - { WM_CHAR, DW_SIGNAL_KEY_PRESS }, - { WM_LBUTTONDOWN, DW_SIGNAL_BUTTON_PRESS }, - { WM_LBUTTONUP, DW_SIGNAL_BUTTON_PRESS }, - { WM_MOUSEMOVE, DW_SIGNAL_MOTION_NOTIFY }, - { WM_CLOSE, DW_SIGNAL_DELETE }, - { WM_PAINT, DW_SIGNAL_EXPOSE }, - { WM_COMMAND, DW_SIGNAL_CLICKED }, - { NM_DBLCLK, DW_SIGNAL_ITEM_ENTER }, - { NM_RCLICK, DW_SIGNAL_ITEM_CONTEXT }, - { LBN_SELCHANGE, DW_SIGNAL_LIST_SELECT }, - { TVN_SELCHANGED, DW_SIGNAL_ITEM_SELECT }, - { WM_SETFOCUS, DW_SIGNAL_SET_FOCUS }, - { WM_VSCROLL, DW_SIGNAL_VALUE_CHANGED }, - { TCN_SELCHANGE, DW_SIGNAL_SWITCH_PAGE }, - { LVN_COLUMNCLICK, DW_SIGNAL_COLUMN_CLICK }, - { TVN_ITEMEXPANDED,DW_SIGNAL_TREE_EXPAND } -}; - -#ifdef BUILD_DLL -void Win32_Set_Instance(HINSTANCE hInstance) -{ - DWInstance = hInstance; -} -#else -char **_convertargs(int *count, char *start) -{ - char *tmp, *argstart, **argv; - int loc = 0, inquotes = 0; - - (*count) = 1; - - tmp = start; - - /* Count the number of entries */ - if(*start) - { - (*count)++; - - while(*tmp) - { - if(*tmp == '"' && inquotes) - inquotes = 0; - else if(*tmp == '"' && !inquotes) - inquotes = 1; - else if(*tmp == ' ' && !inquotes) - { - /* Push past any white space */ - while(*(tmp+1) == ' ') - tmp++; - /* If we aren't at the end of the command - * line increment the count. - */ - if(*(tmp+1)) - (*count)++; - } - tmp++; - } - } - - argv = (char **)malloc(sizeof(char *) * ((*count)+1)); - argv[0] = malloc(260); - GetModuleFileName(DWInstance, argv[0], 260); - - argstart = tmp = start; - - if(*start) - { - loc = 1; - - while(*tmp) - { - if(*tmp == '"' && inquotes) - { - *tmp = 0; - inquotes = 0; - } - else if(*tmp == '"' && !inquotes) - { - argstart = tmp+1; - inquotes = 1; - } - else if(*tmp == ' ' && !inquotes) - { - *tmp = 0; - argv[loc] = strdup(argstart); - - /* Push past any white space */ - while(*(tmp+1) == ' ') - tmp++; - - /* Move the start pointer */ - argstart = tmp+1; - - /* If we aren't at the end of the command - * line increment the count. - */ - if(*(tmp+1)) - loc++; - } - tmp++; - } - if(*argstart) - argv[loc] = strdup(argstart); - } - argv[loc+1] = NULL; - return argv; -} - -/* Ok this is a really big hack but what the hell ;) */ -int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) -{ - char **argv; - int argc; - - DWInstance = hInstance; - - argv = _convertargs(&argc, lpCmdLine); - - return main(argc, argv); -} -#endif - -/* This should return true for WinNT/2K/XP and false on Win9x */ -int IsWinNT(void) -{ - static int isnt = -1; - - if(isnt == -1) - { - if (GetVersion() < 0x80000000) - isnt = 1; - else - isnt = 0; - } - return isnt; -} - -DWORD GetDllVersion(LPCTSTR lpszDllName) -{ - - HINSTANCE hinstDll; - DWORD dwVersion = 0; - - hinstDll = LoadLibrary(lpszDllName); - - if(hinstDll) - { - DLLGETVERSIONPROC pDllGetVersion; - - pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion"); - - /* Because some DLLs might not implement this function, you - * must test for it explicitly. Depending on the particular - * DLL, the lack of a DllGetVersion function can be a useful - * indicator of the version. - */ - if(pDllGetVersion) - { - DLLVERSIONINFO dvi; - HRESULT hr; - - ZeroMemory(&dvi, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - - hr = (*pDllGetVersion)(&dvi); - - if(SUCCEEDED(hr)) - { - dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion); - } - } - - FreeLibrary(hinstDll); - } - return dwVersion; -} - -/* This function adds a signal handler callback into the linked list. - */ -void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data) -{ - SignalHandler *new = malloc(sizeof(SignalHandler)); - - new->message = message; - new->window = window; - new->id = id; - new->signalfunction = signalfunction; - new->data = data; - new->next = NULL; - - if (!Root) - Root = new; - else - { - SignalHandler *prev = NULL, *tmp = Root; - while(tmp) - { - if(tmp->message == message && - tmp->window == window && - tmp->id == id && - tmp->signalfunction == signalfunction) - { - tmp->data = data; - free(new); - return; - } - prev = tmp; - tmp = tmp->next; - } - if(prev) - prev->next = new; - else - Root = new; - } -} - -/* Finds the message number for a given signal name */ -ULONG _findsigmessage(char *signame) -{ - int z; - - for(z=0;z<SIGNALMAX;z++) - { - if(stricmp(signame, SignalTranslate[z].name) == 0) - return SignalTranslate[z].message; - } - return 0L; -} - -/* This function removes and handlers on windows and frees - * the user memory allocated to it. - */ -BOOL CALLBACK _free_window_memory(HWND handle, LPARAM lParam) -{ - ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - HFONT oldfont = (HFONT)SendMessage(handle, WM_GETFONT, 0, 0); - HICON oldicon = (HICON)SendMessage(handle, WM_GETICON, 0, 0); - char tmpbuf[100]; - - /* Delete font, icon and bitmap GDI objects in use */ - if(oldfont) - DeleteObject(oldfont); - if(oldicon) - DeleteObject(oldicon); - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, STATICCLASSNAME, strlen(STATICCLASSNAME)+1)==0) - { - HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, STM_GETIMAGE, IMAGE_BITMAP, 0); - - if(oldbitmap) - DeleteObject(oldbitmap); - } - if(strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0) - { - HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, BM_GETIMAGE, IMAGE_BITMAP, 0); - - if(oldbitmap) - DeleteObject(oldbitmap); - } - else if(strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1)==0) - { - Box *box = (Box *)thiscinfo; - - if(box->count && box->items) - free(box->items); - } - else if(strnicmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0) - { - void *data = dw_window_get_data(handle, "_dw_percent"); - - if(data) - free(data); - } - else if(strnicmp(tmpbuf, WC_TREEVIEW, strlen(WC_TREEVIEW)+1)==0) - { - dw_tree_clear(handle); - } - else if(strnicmp(tmpbuf, WC_TABCONTROL, strlen(WC_TABCONTROL)+1)==0) /* Notebook */ - { - NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); - - if(array) - { - int z, refid = -1; - - for(z=0;z<256;z++) - { - if(array[z]) - { - _free_window_memory(array[z]->hwnd, 0); - EnumChildWindows(array[z]->hwnd, _free_window_memory, 0); - DestroyWindow(array[z]->hwnd); - free(array[z]); - } - } - free(array); - } - } - - dw_signal_disconnect_by_window(handle); - - if(thiscinfo) - { - SubclassWindow(handle, thiscinfo->pOldProc); - - /* Delete the brush so as not to leak GDI objects */ - if(thiscinfo->hbrush) - DeleteObject(thiscinfo->hbrush); - - /* Free user data linked list memory */ - if(thiscinfo->root) - dw_window_set_data(handle, NULL, NULL); - - SetWindowLongPtr(handle, GWLP_USERDATA, 0); - free(thiscinfo); - } - return TRUE; -} - -void _free_menu_data(HMENU menu) -{ -#ifndef WINNT_COMPAT - int i, count = GetMenuItemCount(menu); - - for(i=0;i<count;i++) - { - MENUITEMINFO mii; - - mii.cbSize = sizeof(MENUITEMINFO); - mii.fMask = MIIM_SUBMENU; - - if(GetMenuItemInfo(menu, i, TRUE, &mii) - && mii.hSubMenu) - _free_menu_data(mii.hSubMenu); - } -#endif - dw_signal_disconnect_by_name((HWND)menu, DW_SIGNAL_CLICKED); -} - -/* Convert to our internal color scheme */ -ULONG _internal_color(ULONG color) -{ - if(color == DW_CLR_DEFAULT) - return DW_RGB_TRANSPARENT; - if(color < 18) - return DW_RGB(_red[color], _green[color], _blue[color]); - return color; -} - -/* This function returns 1 if the window (widget) handle - * passed to it is a valid window that can gain input focus. - */ -int _validate_focus(HWND handle) -{ - char tmpbuf[100]; - - if(!handle) - return 0; - - if(!IsWindowEnabled(handle)) - return 0; - - GetClassName(handle, tmpbuf, 99); - - /* These are the window classes which can - * obtain input focus. - */ - if(strnicmp(tmpbuf, EDITCLASSNAME, strlen(EDITCLASSNAME)+1)==0 || /* Entryfield */ - strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0 || /* Button */ - strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0 || /* Combobox */ - strnicmp(tmpbuf, LISTBOXCLASSNAME, strlen(LISTBOXCLASSNAME)+1)==0 || /* List box */ - strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0 || /* Spinbutton */ - strnicmp(tmpbuf, TRACKBAR_CLASS, strlen(TRACKBAR_CLASS)+1)==0 || /* Slider */ - strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW)+1)== 0 || /* Container */ - strnicmp(tmpbuf, WC_TREEVIEW, strlen(WC_TREEVIEW)+1)== 0) /* Tree */ - return 1; - return 0; -} - -HWND _normalize_handle(HWND handle) -{ - char tmpbuf[100] = ""; - - GetClassName(handle, tmpbuf, 99); - if(strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS))==0) /* Spinner */ - { - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - - if(cinfo && cinfo->buddy) - return cinfo->buddy; - } - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME))==0) /* Combobox */ - { - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - - if(cinfo && cinfo->buddy) - return cinfo->buddy; - } - return handle; -} - -int _focus_check_box(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=box->count-1;z>-1;z--) - { - 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)) - 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 - { - char tmpbuf[100] = ""; - - GetClassName(box->items[z].hwnd, tmpbuf, 99); - - 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 *)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"); - - if(mybox) - { - Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA); - - if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem)) - return 1; - } - } - else if(strnicmp(tmpbuf, WC_TABCONTROL, strlen(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(notebox, handle, start == 3 ? 3 : 0, 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)) - 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 - { - char tmpbuf[100] = ""; - - GetClassName(box->items[z].hwnd, tmpbuf, 99); - - 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 *)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(strnicmp(tmpbuf, WC_TABCONTROL, strlen(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; - } - } - } - } - } - } - return 0; -} - -/* This function finds the first widget in the - * layout and moves the current focus to it. - */ -void _initial_focus(HWND handle) -{ - Box *thisbox; - char tmpbuf[100]; - - if(!handle) - return; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, ClassName, strlen(ClassName))!=0) - return; - - - if(handle) - thisbox = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA); - - if(thisbox) - { - _focus_check_box(thisbox, handle, 3, thisbox->defaultitem); - } -} - -HWND _toplevel_window(HWND handle) -{ - HWND box, lastbox = GetParent(handle); - - /* Find the toplevel window */ - while((box = GetParent(lastbox))) - { - lastbox = box; - } - if(lastbox) - return lastbox; - return handle; -} - -/* This function finds the current widget in the - * layout and moves the current focus to the next item. - */ -void _shift_focus(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(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); - } -} - -/* ResetWindow: - * Resizes window to the exact same size to trigger - * recalculation of frame. - */ -void _ResetWindow(HWND hwndFrame) -{ - RECT rcl; - - GetWindowRect(hwndFrame, &rcl); - SetWindowPos(hwndFrame, HWND_TOP, 0, 0, rcl.right - rcl.left, - rcl.bottom - rcl.top - 1, SWP_NOMOVE | SWP_NOZORDER); - SetWindowPos(hwndFrame, HWND_TOP, 0, 0, rcl.right - rcl.left, - rcl.bottom - rcl.top, SWP_NOMOVE | SWP_NOZORDER); -} - -/* This function calculates how much space the widgets and boxes require - * and does expansion as necessary. - */ -int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy, - int pass, int *usedpadx, int *usedpady) -{ - int z, currentx = 0, currenty = 0; - int uymax = 0, uxmax = 0; - int upymax = 0, upxmax = 0; - /* Used for the SIZEEXPAND */ - int nux = *usedx, nuy = *usedy; - int nupx = *usedpadx, nupy = *usedpady; - - (*usedx) += (thisbox->pad * 2); - (*usedy) += (thisbox->pad * 2); - - if(thisbox->grouphwnd) - { - char *text = dw_window_get_text(thisbox->grouphwnd); - - thisbox->grouppady = 0; - - if(text) - { - dw_font_text_extents(thisbox->grouphwnd, 0, text, NULL, &thisbox->grouppady); - dw_free(text); - } - - if(thisbox->grouppady) - thisbox->grouppady += 3; - else - thisbox->grouppady = 6; - - thisbox->grouppadx = 6; - - (*usedx) += thisbox->grouppadx; - (*usedpadx) += thisbox->grouppadx; - (*usedy) += thisbox->grouppady; - (*usedpady) += thisbox->grouppady; - } - - for(z=0;z<thisbox->count;z++) - { - if(thisbox->items[z].type == TYPEBOX) - { - int initialx, initialy; - Box *tmp = (Box *)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA); - - initialx = x - (*usedx); - initialy = y - (*usedy); - - if(tmp) - { - int newx, newy; - int nux = *usedx, nuy = *usedy; - int upx = *usedpadx + (tmp->pad*2), upy = *usedpady + (tmp->pad*2); - - /* On the second pass we know how big the box needs to be and how - * much space we have, so we can calculate a ratio for the new box. - */ - if(pass == 2) - { - int deep = *depth + 1; - - _resize_box(tmp, &deep, x, y, &nux, &nuy, 1, &upx, &upy); - - tmp->upx = upx - *usedpadx; - tmp->upy = upy - *usedpady; - - newx = x - nux; - newy = y - nuy; - - tmp->width = thisbox->items[z].width = initialx - newx; - tmp->height = thisbox->items[z].height = initialy - newy; - - tmp->parentxratio = thisbox->xratio; - tmp->parentyratio = thisbox->yratio; - - tmp->parentpad = tmp->pad; - - /* Just in case */ - tmp->xratio = thisbox->xratio; - tmp->yratio = thisbox->yratio; - - if(thisbox->type == DW_VERT) - { - int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppady; - - if((thisbox->items[z].width - tmppad)!=0) - tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmppad))/((float)(thisbox->items[z].width-tmppad)); - } - else - { - if((thisbox->items[z].width-tmp->upx)!=0) - tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx)); - } - if(thisbox->type == DW_HORZ) - { - int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppadx; - - if((thisbox->items[z].height-tmppad)!=0) - tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmppad))/((float)(thisbox->items[z].height-tmppad)); - } - else - { - if((thisbox->items[z].height-tmp->upy)!=0) - tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy)); - } - - nux = *usedx; nuy = *usedy; - upx = *usedpadx + (tmp->pad*2); upy = *usedpady + (tmp->pad*2); - } - - (*depth)++; - - _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy); - - (*depth)--; - - newx = x - nux; - newy = y - nuy; - - tmp->minwidth = thisbox->items[z].width = initialx - newx; - tmp->minheight = thisbox->items[z].height = initialy - newy; - } - } - - if(pass > 1 && *depth > 0) - { - if(thisbox->type == DW_VERT) - { - int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppadx; - - if((thisbox->minwidth-tmppad) == 0) - thisbox->items[z].xratio = 1.0; - else - thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-tmppad))/((float)(thisbox->minwidth-tmppad)); - } - else - { - if(thisbox->minwidth-thisbox->upx == 0) - thisbox->items[z].xratio = 1.0; - else - thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx)); - } - - if(thisbox->type == DW_HORZ) - { - int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppady; - - if((thisbox->minheight-tmppad) == 0) - thisbox->items[z].yratio = 1.0; - else - thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-tmppad))/((float)(thisbox->minheight-tmppad)); - } - else - { - if(thisbox->minheight-thisbox->upy == 0) - thisbox->items[z].yratio = 1.0; - else - thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy)); - } - - if(thisbox->items[z].type == TYPEBOX) - { - Box *tmp = (Box *)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA); - - if(tmp) - { - tmp->parentxratio = thisbox->items[z].xratio; - tmp->parentyratio = thisbox->items[z].yratio; - } - } - } - else - { - thisbox->items[z].xratio = thisbox->xratio; - thisbox->items[z].yratio = thisbox->yratio; - } - - if(thisbox->type == DW_VERT) - { - int itemwidth = (thisbox->items[z].pad*2) + thisbox->items[z].width; - - if(itemwidth > uxmax) - uxmax = itemwidth; - if(thisbox->items[z].hsize != SIZEEXPAND) - { - if(itemwidth > upxmax) - upxmax = itemwidth; - } - else - { - if(thisbox->items[z].pad*2 > upxmax) - upxmax = thisbox->items[z].pad*2; - } - } - else - { - if(thisbox->items[z].width == -1) - { - /* figure out how much space this item requires */ - /* thisbox->items[z].width = */ - } - else - { - (*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2); - if(thisbox->items[z].hsize != SIZEEXPAND) - (*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width; - else - (*usedpadx) += thisbox->items[z].pad*2; - } - } - if(thisbox->type == DW_HORZ) - { - int itemheight = (thisbox->items[z].pad*2) + thisbox->items[z].height; - - if(itemheight > uymax) - uymax = itemheight; - if(thisbox->items[z].vsize != SIZEEXPAND) - { - if(itemheight > upymax) - upymax = itemheight; - } - else - { - if(thisbox->items[z].pad*2 > upymax) - upymax = thisbox->items[z].pad*2; - } - } - else - { - if(thisbox->items[z].height == -1) - { - /* figure out how much space this item requires */ - /* thisbox->items[z].height = */ - } - else - { - (*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2); - if(thisbox->items[z].vsize != SIZEEXPAND) - (*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height; - else - (*usedpady) += thisbox->items[z].pad*2; - } - } - } - - (*usedx) += uxmax; - (*usedy) += uymax; - (*usedpadx) += upxmax; - (*usedpady) += upymax; - - currentx += thisbox->pad; - currenty += thisbox->pad; - - if(thisbox->grouphwnd) - { - currentx += 3; - currenty += thisbox->grouppady - 3; - } - - /* The second pass is for expansion and actual placement. */ - if(pass > 1) - { - /* Any SIZEEXPAND items should be set to uxmax/uymax */ - for(z=0;z<thisbox->count;z++) - { - if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == DW_VERT) - thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2); - if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == DW_HORZ) - thisbox->items[z].height = uymax-(thisbox->items[z].pad*2); - /* Run this code segment again to finalize the sized after setting uxmax/uymax values. */ - if(thisbox->items[z].type == TYPEBOX) - { - Box *tmp = (Box *)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA); - - if(tmp) - { - if(*depth > 0) - { - float calcval; - - if(thisbox->type == DW_VERT) - { - calcval = (float)(tmp->minwidth-((thisbox->items[z].pad*2)+(thisbox->pad*2))); - if(calcval == 0.0) - tmp->xratio = thisbox->xratio; - else - tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval; - tmp->width = thisbox->items[z].width; - } - if(thisbox->type == DW_HORZ) - { - calcval = (float)(tmp->minheight-((thisbox->items[z].pad*2)+(thisbox->pad*2))); - if(calcval == 0.0) - tmp->yratio = thisbox->yratio; - else - tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval; - tmp->height = thisbox->items[z].height; - } - } - - (*depth)++; - - _resize_box(tmp, depth, x, y, &nux, &nuy, 3, &nupx, &nupy); - - (*depth)--; - - } - } - } - - for(z=0;z<(thisbox->count);z++) - { - int height = thisbox->items[z].height; - int width = thisbox->items[z].width; - int pad = thisbox->items[z].pad; - HWND handle = thisbox->items[z].hwnd; - int vectorx, vectory; - - /* When upxmax != pad*2 then ratios are incorrect. */ - vectorx = (int)((width*thisbox->items[z].xratio)-width); - vectory = (int)((height*thisbox->items[z].yratio)-height); - - if(width > 0 && height > 0) - { - char tmpbuf[100]; - /* This is a hack to fix rounding of the sizing */ - if(*depth == 0) - { - vectorx++; - vectory++; - } - - /* If this item isn't going to expand... reset the vectors to 0 */ - if(thisbox->items[z].vsize != SIZEEXPAND) - vectory = 0; - if(thisbox->items[z].hsize != SIZEEXPAND) - vectorx = 0; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - { - /* Handle special case Combobox */ - MoveWindow(handle, currentx + pad, currenty + pad, - width + vectorx, (height + vectory) + 400, FALSE); - } - else if(strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0) - { - /* Handle special case Spinbutton */ - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - - MoveWindow(handle, currentx + pad + ((width + vectorx) - 20), currenty + pad, - 20, height + vectory, FALSE); - - if(cinfo) - { - MoveWindow(cinfo->buddy, currentx + pad, currenty + pad, - (width + vectorx) - 20, height + vectory, FALSE); - } - } - else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0) - { - /* 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 cx = width + vectorx; - int cy = height + vectory; - - MoveWindow(handle, currentx + pad, currenty + pad, - cx, cy, FALSE); - - if(cx > 0 && cy > 0 && percent) - _handle_splitbar_resize(handle, *percent, type, cx, cy); - } - else if(strnicmp(tmpbuf, STATICCLASSNAME, strlen(STATICCLASSNAME)+1)==0) - { - /* Handle special case Vertically Center static text */ - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - - if(cinfo && cinfo->vcenter) - { - /* We are centered so calculate a new position */ - char tmpbuf[1024]; - int textheight, diff, total = height + vectory; - - GetWindowText(handle, tmpbuf, 1023); - - /* Figure out how big the text is */ - dw_font_text_extents(handle, 0, tmpbuf, 0, &textheight); - - diff = (total - textheight) / 2; - - MoveWindow(handle, currentx + pad, currenty + pad + diff, - width + vectorx, height + vectory - diff, FALSE); - } - else - { - MoveWindow(handle, currentx + pad, currenty + pad, - width + vectorx, height + vectory, FALSE); - } - } - else - { - /* Everything else */ - MoveWindow(handle, currentx + pad, currenty + pad, - width + vectorx, height + vectory, FALSE); - if(thisbox->items[z].type == TYPEBOX) - { - Box *boxinfo = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA); - - if(boxinfo && boxinfo->grouphwnd) - MoveWindow(boxinfo->grouphwnd, 0, 0, - width + vectorx, height + vectory, FALSE); - - } - } - - /* Notebook dialog requires additional processing */ - if(strncmp(tmpbuf, WC_TABCONTROL, strlen(WC_TABCONTROL))==0) - { - RECT rect; - NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); - int pageid = TabCtrl_GetCurSel(handle); - - if(pageid > -1 && array && array[pageid]) - { - GetClientRect(handle,&rect); - TabCtrl_AdjustRect(handle,FALSE,&rect); - MoveWindow(array[pageid]->hwnd, rect.left, rect.top, - rect.right - rect.left, rect.bottom-rect.top, FALSE); - } - } - - if(thisbox->type == DW_HORZ) - currentx += width + vectorx + (pad * 2); - if(thisbox->type == DW_VERT) - currenty += height + vectory + (pad * 2); - } - } - } - return 0; -} - -void _do_resize(Box *thisbox, int x, int y) -{ - if(x != 0 && y != 0) - { - if(thisbox) - { - int usedx = 0, usedy = 0, depth = 0, usedpadx = 0, usedpady = 0; - - _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady); - - if(usedx-usedpadx == 0 || usedy-usedpady == 0) - return; - - thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx)); - thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady)); - - usedpadx = usedpady = usedx = usedy = depth = 0; - - _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady); - } - } -} - -int _HandleScroller(HWND handle, int pos, int which) -{ - SCROLLINFO si; - - si.cbSize = sizeof(SCROLLINFO); - si.fMask = SIF_ALL; - - SendMessage(handle, SBM_GETSCROLLINFO, 0, (LPARAM)&si); - - switch(which) - { - case SB_THUMBTRACK: - return pos; - /*case SB_PAGEDOWN:*/ - case SB_PAGELEFT: - pos = si.nPos - si.nPage; - if(pos < si.nMin) - pos = si.nMin; - return pos; - /*case SB_PAGEUP:*/ - case SB_PAGERIGHT: - pos = si.nPos + si.nPage; - if(pos > (si.nMax - si.nPage) + 1) - pos = (si.nMax - si.nPage) + 1; - return pos; - /*case SB_LINEDOWN:*/ - case SB_LINELEFT: - pos = si.nPos - 1; - if(pos < si.nMin) - pos = si.nMin; - return pos; - /*case SB_LINEUP:*/ - case SB_LINERIGHT: - pos = si.nPos + 1; - if(pos > (si.nMax - si.nPage) + 1) - pos = (si.nMax - si.nPage) + 1; - return pos; - } - return -1; -} - -#ifndef WINNT_COMPAT -HMENU _get_owner(HMENU menu) -{ - MENUINFO mi; - - mi.cbSize = sizeof(MENUINFO); - mi.fMask = MIM_MENUDATA; - - if(GetMenuInfo(menu, &mi)) - return (HMENU)mi.dwMenuData; - return (HMENU)0; -} - -/* Find the desktop window handle */ -HMENU _menu_owner(HMENU handle) -{ - HMENU menuowner = 0, lastowner = _get_owner(handle); - - /* Find the toplevel menu */ - while((menuowner = _get_owner(lastowner)) != 0) - { - if(menuowner == (HMENU)1) - return lastowner; - lastowner = menuowner; - } - return (HMENU)0; -} -#endif - -/* The main window procedure for Dynamic Windows, all the resizing code is done here. */ -BOOL CALLBACK _wndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) -{ - int result = -1, taskbar = FALSE; - static int command_active = 0; - SignalHandler *tmp = Root; - void (*windowfunc)(PVOID); - ULONG origmsg = msg; - - /* Deal with translating some messages */ - if(msg == WM_USER+2) - { - taskbar = TRUE; - origmsg = msg = (UINT)mp2; /* no else here */ - } - if(msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) - msg = WM_LBUTTONDOWN; - else if(msg == WM_RBUTTONUP || msg == WM_MBUTTONUP) - msg = WM_LBUTTONUP; - else if(msg == WM_HSCROLL) - msg = WM_VSCROLL; - else if(msg == WM_KEYDOWN) /* && mp1 >= VK_F1 && mp1 <= VK_F24) allow ALL special keys */ - msg = WM_CHAR; - - if(result == -1) - { - /* Avoid infinite recursion */ - command_active = 1; - - /* Find any callbacks for this function */ - while(tmp) - { - if(tmp->message == msg || msg == WM_COMMAND || msg == WM_NOTIFY || tmp->message == WM_USER+1) - { - switch(msg) - { - case WM_TIMER: - { - int (*timerfunc)(void *) = tmp->signalfunction; - if(tmp->id == (int)mp1) - { - if(!timerfunc(tmp->data)) - dw_timer_disconnect(tmp->id); - tmp = NULL; - } - result = 0; - } - break; - case WM_SETFOCUS: - { - int (*setfocusfunc)(HWND, void *) = (int (*)(HWND, void *))tmp->signalfunction; - - if(hWnd == tmp->window) - { - result = setfocusfunc(tmp->window, tmp->data); - tmp = NULL; - } - } - break; - case WM_SIZE: - { - int (*sizefunc)(HWND, int, int, void *) = tmp->signalfunction; - - if(hWnd == tmp->window) - { - result = sizefunc(tmp->window, LOWORD(mp2), HIWORD(mp2), tmp->data); - tmp = NULL; - } - } - break; - case WM_LBUTTONDOWN: - { - int (*buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; - - if(hWnd == tmp->window) - { - int button; - - switch(origmsg) - { - case WM_LBUTTONDOWN: - button = 1; - break; - case WM_RBUTTONDOWN: - button = 2; - break; - case WM_MBUTTONDOWN: - button = 3; - break; - } - if(taskbar) - { - POINT ptl; - GetCursorPos(&ptl); - result = buttonfunc(tmp->window, ptl.x, ptl.y, button, tmp->data); - } - else - { - POINTS pts = MAKEPOINTS(mp2); - result = buttonfunc(tmp->window, pts.x, pts.y, button, tmp->data); - } - tmp = NULL; - } - } - break; - case WM_LBUTTONUP: - { - int (*buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; - - if(hWnd == tmp->window) - { - int button; - - switch(origmsg) - { - case WM_LBUTTONUP: - button = 1; - break; - case WM_RBUTTONUP: - button = 2; - break; - case WM_MBUTTONUP: - button = 3; - break; - } - if(taskbar) - { - POINT ptl; - GetCursorPos(&ptl); - result = buttonfunc(tmp->window, ptl.x, ptl.y, button, tmp->data); - } - else - { - POINTS pts = MAKEPOINTS(mp2); - result = buttonfunc(tmp->window, pts.x, pts.y, button, tmp->data); - } - tmp = NULL; - } - } - break; - case WM_MOUSEMOVE: - { - POINTS pts = MAKEPOINTS(mp2); - int (*motionfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; - - if(hWnd == tmp->window) - { - int keys = 0; - - if (mp1 & MK_LBUTTON) - keys = DW_BUTTON1_MASK; - if (mp1 & MK_RBUTTON) - keys |= DW_BUTTON2_MASK; - if (mp1 & MK_MBUTTON) - keys |= DW_BUTTON3_MASK; - - result = motionfunc(tmp->window, pts.x, pts.y, keys, tmp->data); - tmp = NULL; - } - } - break; - case WM_CHAR: - { - int (*keypressfunc)(HWND, char, int, int, void *) = tmp->signalfunction; - - if(hWnd == tmp->window || _toplevel_window(hWnd) == tmp->window) - { - int special = 0; - char ch = 0; - - if(GetAsyncKeyState(VK_SHIFT) & 0x8000) - special |= KC_SHIFT; - if(GetAsyncKeyState(VK_CONTROL) & 0x8000) - special |= KC_CTRL; - if(mp2 & (1 << 29)) - special |= KC_ALT; - - if(origmsg == WM_CHAR && mp1 < 128) - ch = (char)mp1; - - result = keypressfunc(tmp->window, ch, mp1, special, tmp->data); - tmp = NULL; - } - } - break; - case WM_CLOSE: - { - int (*closefunc)(HWND, void *) = tmp->signalfunction; - - if(hWnd == tmp->window) - { - result = closefunc(tmp->window, tmp->data); - tmp = NULL; - } - } - break; - case WM_PAINT: - { - PAINTSTRUCT ps; - DWExpose exp; - int (*exposefunc)(HWND, DWExpose *, void *) = tmp->signalfunction; - - if(hWnd == tmp->window) - { - BeginPaint(hWnd, &ps); - exp.x = ps.rcPaint.left; - exp.y = ps.rcPaint.top; - exp.width = ps.rcPaint.right - ps.rcPaint.left; - exp.height = ps.rcPaint.bottom - ps.rcPaint.top; - result = exposefunc(hWnd, &exp, tmp->data); - EndPaint(hWnd, &ps); - } - } - break; - case WM_NOTIFY: - { - if(tmp->message == TVN_SELCHANGED || - tmp->message == NM_RCLICK || - tmp->message == TVN_ITEMEXPANDED) - { - NMTREEVIEW FAR *tem=(NMTREEVIEW FAR *)mp2; - char tmpbuf[100]; - - GetClassName(tem->hdr.hwndFrom, tmpbuf, 99); - - if(strnicmp(tmpbuf, WC_TREEVIEW, strlen(WC_TREEVIEW))==0) - { - if(tem->hdr.code == TVN_SELCHANGED && tmp->message == TVN_SELCHANGED) - { - if(tmp->window == tem->hdr.hwndFrom && !dw_window_get_data(tmp->window, "_dw_select_item")) - { - int (*treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = tmp->signalfunction; - TVITEM tvi; - void **ptrs; - - tvi.mask = TVIF_HANDLE; - tvi.hItem = tem->itemNew.hItem; - - 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]); - - tmp = NULL; - } - } - else if(tem->hdr.code == TVN_ITEMEXPANDED && tmp->message == TVN_ITEMEXPANDED) - { - if(tmp->window == tem->hdr.hwndFrom && tem->action == TVE_EXPAND) - { - int (*treeexpandfunc)(HWND, HTREEITEM, void *) = tmp->signalfunction; - - result = treeexpandfunc(tmp->window, tem->itemNew.hItem, tmp->data); - tmp = NULL; - } - } - else if(tem->hdr.code == NM_RCLICK && tmp->message == NM_RCLICK) - { - if(tmp->window == tem->hdr.hwndFrom) - { - int (*containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction; - HTREEITEM hti, last; - TVITEM tvi; - TVHITTESTINFO thi; - void **ptrs = NULL; - LONG x, y; - - dw_pointer_query_pos(&x, &y); - - thi.pt.x = x; - thi.pt.y = y; - - MapWindowPoints(HWND_DESKTOP, tmp->window, &thi.pt, 1); - - last = TreeView_GetSelection(tmp->window); - hti = TreeView_HitTest(tmp->window, &thi); - - if(hti) - { - tvi.mask = TVIF_HANDLE; - tvi.hItem = hti; - - TreeView_GetItem(tmp->window, &tvi); - TreeView_SelectItem(tmp->window, hti); - - ptrs = (void **)tvi.lParam; - } - containercontextfunc(tmp->window, ptrs ? (char *)ptrs[0] : NULL, x, y, tmp->data, ptrs ? ptrs[1] : NULL); - tmp = NULL; - } - } - } - else if(strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW)+1)==0) - { - if(tem->hdr.code == LVN_ITEMCHANGED && tmp->message == TVN_SELCHANGED) - { - if(tmp->window == tem->hdr.hwndFrom) - { - LV_ITEM lvi; - int iItem; - - iItem = ListView_GetNextItem(tmp->window, -1, LVNI_SELECTED); - - memset(&lvi, 0, sizeof(LV_ITEM)); - - if(iItem > -1) - { - int (*treeselectfunc)(HWND, HWND, char *, void *, void *) = tmp->signalfunction; - - 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); - tmp = NULL; - } - } - } - } - } - else if(tmp->message == TCN_SELCHANGE) - { - NMHDR FAR *tem=(NMHDR FAR *)mp2; - if(tmp->window == tem->hwndFrom && tem->code == tmp->message) - { - int (*switchpagefunc)(HWND, unsigned long, void *) = tmp->signalfunction; - unsigned long num=dw_notebook_page_query(tem->hwndFrom); - result = switchpagefunc(tem->hwndFrom, num, tmp->data); - tmp = NULL; - } - } - else if(tmp->message == LVN_COLUMNCLICK) - { - NMLISTVIEW FAR *tem=(NMLISTVIEW FAR *)mp2; - if(tmp->window == tem->hdr.hwndFrom && tem->hdr.code == tmp->message) - { - int (*columnclickfunc)(HWND, int, void *) = tmp->signalfunction; - result = columnclickfunc(tem->hdr.hwndFrom, tem->iSubItem, tmp->data); - tmp = NULL; - } - } - } - break; - case WM_COMMAND: - { - int (*clickfunc)(HWND, void *) = tmp->signalfunction; - HWND command; - ULONG passthru = (ULONG)LOWORD(mp1); - ULONG message = HIWORD(mp1); - - command = (HWND)passthru; - - if(message == LBN_SELCHANGE || message == CBN_SELCHANGE) - { - int (*listboxselectfunc)(HWND, int, void *) = tmp->signalfunction; - - if(tmp->message == LBN_SELCHANGE && tmp->window == (HWND)mp2) - { - result = listboxselectfunc(tmp->window, dw_listbox_selected(tmp->window), tmp->data); - tmp = NULL; - } - } -#ifndef WINNT_COMPAT - else if(tmp->id && passthru == tmp->id) - { - HMENU hwndmenu = GetMenu(hWnd), menuowner = _menu_owner((HMENU)tmp->window); - - if(menuowner == hwndmenu || !menuowner) - { - result = clickfunc(tmp->window, tmp->data); - tmp = NULL; - } - } /* Make sure it's the right window, and the right ID */ -#endif - else if(tmp->window < (HWND)65536 && command == tmp->window) - { - result = clickfunc(popup ? popup : tmp->window, tmp->data); - tmp = NULL; - } - } - break; - case WM_HSCROLL: - case WM_VSCROLL: - { - char tmpbuf[100]; - HWND handle = (HWND)mp2; - int (*valuechangefunc)(HWND, int, void *) = tmp->signalfunction; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, TRACKBAR_CLASS, strlen(TRACKBAR_CLASS)+1)==0) - { - - if(handle == tmp->window) - { - int value = (int)SendMessage(handle, TBM_GETPOS, 0, 0); - int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0); - ULONG currentstyle = GetWindowLong(handle, GWL_STYLE); - - if(currentstyle & TBS_VERT) - result = valuechangefunc(tmp->window, max - value, tmp->data); - else - result = valuechangefunc(tmp->window, value, tmp->data); - tmp = NULL; - } - } - else if(strnicmp(tmpbuf, SCROLLBARCLASSNAME, strlen(SCROLLBARCLASSNAME)+1)==0) - { - if(handle == tmp->window) - { - int value = _HandleScroller(handle, (int)HIWORD(mp1), (int)LOWORD(mp1)); - - if(value > -1) - { - dw_scrollbar_set_pos(tmp->window, value); - result = valuechangefunc(tmp->window, value, tmp->data); - } - tmp = NULL; - msg = 0; - } - } - } - break; - } - } - if(tmp) - tmp = tmp->next; - } - command_active = 0; - } - - /* Now that any handlers are done... do normal processing */ - switch( msg ) - { - case WM_PAINT: - { - PAINTSTRUCT ps; - - BeginPaint(hWnd, &ps); - EndPaint(hWnd, &ps); - } - break; - case WM_SIZE: - { - static int lastx = -1, lasty = -1; - static HWND lasthwnd = 0; - - if(lastx != LOWORD(mp2) || lasty != HIWORD(mp2) || lasthwnd != hWnd) - { - Box *mybox = (Box *)GetWindowLongPtr(hWnd, GWLP_USERDATA); - - if(mybox && mybox->count) - { - lastx = LOWORD(mp2); - lasty = HIWORD(mp2); - lasthwnd = hWnd; - - ShowWindow(mybox->items[0].hwnd, SW_HIDE); - _do_resize(mybox,LOWORD(mp2),HIWORD(mp2)); - ShowWindow(mybox->items[0].hwnd, SW_SHOW); - return 0; - } - } - } - break; - case WM_CHAR: - if(LOWORD(mp1) == '\t') - { - if(GetAsyncKeyState(VK_SHIFT) & 0x8000) - _shift_focus_back(hWnd); - else - _shift_focus(hWnd); - return TRUE; - } - break; - case WM_USER: - windowfunc = (void *)mp1; - - if(windowfunc) - windowfunc((void *)mp2); - break; - case WM_USER+5: - _free_menu_data((HMENU)mp1); - DestroyMenu((HMENU)mp1); - break; - case WM_NOTIFY: - { - NMHDR FAR *tem=(NMHDR FAR *)mp2; - - if(tem->code == TCN_SELCHANGING) - { - int num=TabCtrl_GetCurSel(tem->hwndFrom); - NotebookPage **array = (NotebookPage **)dw_window_get_data(tem->hwndFrom, "_dw_array"); - - if(num > -1 && array && array[num]) - SetParent(array[num]->hwnd, DW_HWND_OBJECT); - - } - else if(tem->code == TCN_SELCHANGE) - { - int num=TabCtrl_GetCurSel(tem->hwndFrom); - NotebookPage **array = (NotebookPage **)dw_window_get_data(tem->hwndFrom, "_dw_array"); - - if(num > -1 && array && array[num]) - SetParent(array[num]->hwnd, tem->hwndFrom); - - _resize_notebook_page(tem->hwndFrom, num); - } - } - break; - case WM_HSCROLL: - case WM_VSCROLL: - { - HWND handle = (HWND)mp2; - - if(dw_window_get_data(handle, "_dw_scrollbar")) - { - int value = _HandleScroller(handle, (int)HIWORD(mp1), (int)LOWORD(mp1)); - - if(value > -1) - dw_scrollbar_set_pos(handle, value); - } - } - break; - case WM_GETMINMAXINFO: - { - MINMAXINFO *info = (MINMAXINFO *)mp2; - info->ptMinTrackSize.x = 8; - info->ptMinTrackSize.y = 8; - return 0; - } - break; - case WM_DESTROY: - { - HMENU menu = GetMenu(hWnd); - - if(menu) - _free_menu_data(menu); - - /* Free memory before destroying */ - _free_window_memory(hWnd, 0); - EnumChildWindows(hWnd, _free_window_memory, 0); - } - break; - case WM_CTLCOLORSTATIC: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORBTN: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORDLG: - { - ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr((HWND)mp2, GWLP_USERDATA); - if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) - { - /* Handle foreground */ - if(thiscinfo->fore > -1 && thiscinfo->fore < 18) - { - if(thiscinfo->fore != DW_CLR_DEFAULT) - { - SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore], - _green[thiscinfo->fore], - _blue[thiscinfo->fore])); - } - } - else if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR) - { - SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore), - DW_GREEN_VALUE(thiscinfo->fore), - DW_BLUE_VALUE(thiscinfo->fore))); - } - /* Handle background */ - if(thiscinfo->back > -1 && thiscinfo->back < 18) - { - if(thiscinfo->back == DW_CLR_DEFAULT) - { - HBRUSH hbr = GetSysColorBrush(COLOR_3DFACE); - - SelectObject((HDC)mp1, hbr); - return (LONG)hbr; - } - else - { - SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back], - _green[thiscinfo->back], - _blue[thiscinfo->back])); - if(thiscinfo->hbrush) - DeleteObject(thiscinfo->hbrush); - thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back], - _green[thiscinfo->back], - _blue[thiscinfo->back])); - SelectObject((HDC)mp1, thiscinfo->hbrush); - } - return (LONG)thiscinfo->hbrush; - } - else if((thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR) - { - SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back), - DW_GREEN_VALUE(thiscinfo->back), - DW_BLUE_VALUE(thiscinfo->back))); - if(thiscinfo->hbrush) - DeleteObject(thiscinfo->hbrush); - thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back), - DW_GREEN_VALUE(thiscinfo->back), - DW_BLUE_VALUE(thiscinfo->back))); - SelectObject((HDC)mp1, thiscinfo->hbrush); - return (LONG)thiscinfo->hbrush; - } - } - - } - break; - } - if(result != -1) - return result; - else - return DefWindowProc(hWnd, msg, mp1, mp2); -} - -VOID CALLBACK _TimerProc(HWND hwnd, UINT msg, UINT_PTR idEvent, DWORD dwTime) -{ - _wndproc(hwnd, msg, (WPARAM)idEvent, 0); -} - -BOOL CALLBACK _framewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) -{ - switch( msg ) - { - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - SetActiveWindow(hWnd); - SetFocus(hWnd); - break; - case WM_COMMAND: - case WM_NOTIFY: - _wndproc(hWnd, msg, mp1, mp2); - break; -#if 0 - case WM_ERASEBKGND: - { - ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); - - if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) - return FALSE; - } - break; -#endif - case WM_PAINT: - { - ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); - - if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) - { - PAINTSTRUCT ps; - HDC hdcPaint = BeginPaint(hWnd, &ps); - int success = FALSE; - - if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) - { - /* Handle foreground */ - if(thiscinfo->fore > -1 && thiscinfo->fore < 18) - { - if(thiscinfo->fore != DW_CLR_DEFAULT) - { - SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore], - _green[thiscinfo->fore], - _blue[thiscinfo->fore])); - } - } - else if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR) - { - SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore), - DW_GREEN_VALUE(thiscinfo->fore), - DW_BLUE_VALUE(thiscinfo->fore))); - } - /* Handle background */ - if(thiscinfo->back > -1 && thiscinfo->back < 18) - { - if(thiscinfo->back != DW_CLR_DEFAULT) - { - SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back], - _green[thiscinfo->back], - _blue[thiscinfo->back])); - if(thiscinfo->hbrush) - DeleteObject(thiscinfo->hbrush); - thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back], - _green[thiscinfo->back], - _blue[thiscinfo->back])); - SelectObject(hdcPaint, thiscinfo->hbrush); - Rectangle(hdcPaint, ps.rcPaint.left - 1, ps.rcPaint.top - 1, ps.rcPaint.right + 1, ps.rcPaint.bottom + 1); - success = TRUE; - } - } - else if((thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR) - { - SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back), - DW_GREEN_VALUE(thiscinfo->back), - DW_BLUE_VALUE(thiscinfo->back))); - if(thiscinfo->hbrush) - DeleteObject(thiscinfo->hbrush); - thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back), - DW_GREEN_VALUE(thiscinfo->back), - DW_BLUE_VALUE(thiscinfo->back))); - SelectObject(hdcPaint, thiscinfo->hbrush); - Rectangle(hdcPaint, ps.rcPaint.left - 1, ps.rcPaint.top - 1, ps.rcPaint.right + 1, ps.rcPaint.bottom + 1); - success = TRUE; - } - } - - EndPaint(hWnd, &ps); - if(success) - return FALSE; - } - - } - break; - } - return DefWindowProc(hWnd, msg, mp1, mp2); -} - -BOOL CALLBACK _rendwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) -{ - switch( msg ) - { - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - SetFocus(hWnd); - _wndproc(hWnd, msg, mp1, mp2); - break; - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - case WM_MOUSEMOVE: - case WM_PAINT: - case WM_SIZE: - case WM_COMMAND: - case WM_CHAR: - case WM_KEYDOWN: - _wndproc(hWnd, msg, mp1, mp2); - break; - } - return DefWindowProc(hWnd, msg, mp1, mp2); -} - -BOOL CALLBACK _spinnerwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) -{ - ColorInfo *cinfo; - - cinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); - - if(cinfo) - { - switch( msg ) - { - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_KEYDOWN: - { - BOOL ret; - - if(!cinfo || !cinfo->pOldProc) - ret = DefWindowProc(hWnd, msg, mp1, mp2); - ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); - - /* Tell the edit control that a buttonpress has - * occured and to update it's window title. - */ - if(cinfo && cinfo->buddy) - SendMessage(cinfo->buddy, WM_USER+10, 0, 0); - - SetTimer(hWnd, 100, 100, (TIMERPROC)NULL); - - return ret; - } - break; - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - case WM_KEYUP: - { - BOOL ret; - - if(!cinfo || !cinfo->pOldProc) - ret = DefWindowProc(hWnd, msg, mp1, mp2); - ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); - - /* Tell the edit control that a buttonpress has - * occured and to update it's window title. - */ - if(cinfo && cinfo->buddy) - SendMessage(cinfo->buddy, WM_USER+10, 0, 0); - - KillTimer(hWnd, 100); - - return ret; - } - break; - case WM_TIMER: - { - if(mp1 == 100) - { - BOOL ret; - - if(cinfo && cinfo->buddy) - SendMessage(cinfo->buddy, WM_USER+10, 0, 0); - - if(!cinfo || !cinfo->pOldProc) - ret = DefWindowProc(hWnd, msg, mp1, mp2); - ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); - - /* Tell the edit control that a buttonpress has - * occured and to update it's window title. - */ - if(cinfo && cinfo->buddy) - SendMessage(cinfo->buddy, WM_USER+10, 0, 0); - - return ret; - } - } - break; - case WM_USER+10: - { - if(cinfo->buddy) - { - char tempbuf[100] = ""; - long position; - - GetWindowText(cinfo->buddy, tempbuf, 99); - - position = atol(tempbuf); - - if(IS_IE5PLUS) - SendMessage(hWnd, UDM_SETPOS32, 0, (LPARAM)position); - else - SendMessage(hWnd, UDM_SETPOS, 0, (LPARAM)MAKELONG((short)position, 0)); - } - } - break; - } - } - - if(!cinfo || !cinfo->pOldProc) - return DefWindowProc(hWnd, msg, mp1, mp2); - return CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); -} - -void _click_default(HWND handle) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - /* These are the window classes which can - * obtain input focus. - */ - if(strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME))==0) - { - /* Generate click on default item */ - SignalHandler *tmp = Root; - - /* Find any callbacks for this function */ - while(tmp) - { - if(tmp->message == WM_COMMAND) - { - int (*clickfunc)(HWND, void *) = tmp->signalfunction; - - /* Make sure it's the right window, and the right ID */ - if(tmp->window == handle) - { - clickfunc(tmp->window, tmp->data); - tmp = NULL; - } - } - if(tmp) - tmp= tmp->next; - } - } - else - SetFocus(handle); -} - -BOOL CALLBACK _colorwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) -{ - ColorInfo *cinfo; - char tmpbuf[100]; - WNDPROC pOldProc = 0; - - cinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); - - GetClassName(hWnd, tmpbuf, 99); - if(strcmp(tmpbuf, FRAMECLASSNAME) == 0) - cinfo = &(((Box *)cinfo)->cinfo); - - if(cinfo) - { - pOldProc = cinfo->pOldProc; - - switch( msg ) - { - case WM_SETFOCUS: - if(cinfo->combo) - _wndproc(cinfo->combo, msg, mp1, mp2); - else - _wndproc(hWnd, msg, mp1, mp2); - break; - case WM_VSCROLL: - case WM_HSCROLL: - _wndproc(hWnd, msg, mp1, mp2); - break; - case WM_KEYDOWN: - case WM_KEYUP: - { - if(mp1 == VK_UP || mp1 == VK_DOWN) - { - BOOL ret; - - if(!cinfo || !cinfo->pOldProc) - ret = DefWindowProc(hWnd, msg, mp1, mp2); - ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); - - /* Tell the spinner control that a keypress has - * occured and to update it's internal value. - */ - if(cinfo && cinfo->buddy && !cinfo->combo) - PostMessage(hWnd, WM_USER+10, 0, 0); - - if(msg == WM_KEYDOWN) - SetTimer(hWnd, 101, 100, (TIMERPROC)NULL); - else - KillTimer(hWnd, 101); - - return ret; - } - } - break; - case WM_TIMER: - { - if(mp1 == 101) - { - BOOL ret; - - if(!cinfo || !cinfo->pOldProc) - ret = DefWindowProc(hWnd, msg, mp1, mp2); - ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); - - /* Tell the spinner control that a keypress has - * occured and to update it's internal value. - */ - if(cinfo && cinfo->buddy && !cinfo->combo) - PostMessage(hWnd, WM_USER+10, 0, 0); - - return ret; - } - } - break; - case WM_CHAR: - _wndproc(hWnd, msg, mp1, mp2); - if(LOWORD(mp1) == '\t') - { - if(GetAsyncKeyState(VK_SHIFT) & 0x8000) - { - if(cinfo->combo) - _shift_focus_back(cinfo->combo); - else if(cinfo->buddy) - _shift_focus_back(cinfo->buddy); - else - _shift_focus_back(hWnd); - } - else - { - if(cinfo->combo) - _shift_focus(cinfo->combo); - else if(cinfo->buddy) - _shift_focus(cinfo->buddy); - else - _shift_focus(hWnd); - } - return FALSE; - } - else if(LOWORD(mp1) == '\r') - { - if(cinfo->clickdefault) - _click_default(cinfo->clickdefault); - - } - - /* Tell the spinner control that a keypress has - * occured and to update it's internal value. - */ - if(cinfo->buddy && !cinfo->combo) - { - if(IsWinNT()) - PostMessage(cinfo->buddy, WM_USER+10, 0, 0); - else - SendMessage(cinfo->buddy, WM_USER+10, 0, 0); - } - break; - case WM_USER+10: - { - if(cinfo->buddy) - { - long val; - - if(IS_IE5PLUS) - val = (long)SendMessage(cinfo->buddy, UDM_GETPOS32, 0, 0); - else - val = (long)SendMessage(cinfo->buddy, UDM_GETPOS, 0, 0); - - sprintf(tmpbuf, "%d", val); - SetWindowText(hWnd, tmpbuf); - } - } - break; - case WM_CTLCOLORSTATIC: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORBTN: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORDLG: - { - ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr((HWND)mp2, GWLP_USERDATA); - if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) - { - /* Handle foreground */ - if(thiscinfo->fore > -1 && thiscinfo->fore < 18) - { - if(thiscinfo->fore != DW_CLR_DEFAULT) - { - SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore], - _green[thiscinfo->fore], - _blue[thiscinfo->fore])); - } - } - else if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR) - { - SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore), - DW_GREEN_VALUE(thiscinfo->fore), - DW_BLUE_VALUE(thiscinfo->fore))); - } - /* Handle background */ - if(thiscinfo->back > -1 && thiscinfo->back < 18) - { - if(thiscinfo->back == DW_CLR_DEFAULT) - { - HBRUSH hbr = GetSysColorBrush(COLOR_3DFACE); - - SetBkColor((HDC)mp1, GetSysColor(COLOR_3DFACE)); - - - SelectObject((HDC)mp1, hbr); - return (LONG)hbr; - } - else - { - SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back], - _green[thiscinfo->back], - _blue[thiscinfo->back])); - if(thiscinfo->hbrush) - DeleteObject(thiscinfo->hbrush); - thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back], - _green[thiscinfo->back], - _blue[thiscinfo->back])); - SelectObject((HDC)mp1, thiscinfo->hbrush); - } - return (LONG)thiscinfo->hbrush; - } - else if((thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR) - { - SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back), - DW_GREEN_VALUE(thiscinfo->back), - DW_BLUE_VALUE(thiscinfo->back))); - if(thiscinfo->hbrush) - DeleteObject(thiscinfo->hbrush); - thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back), - DW_GREEN_VALUE(thiscinfo->back), - DW_BLUE_VALUE(thiscinfo->back))); - SelectObject((HDC)mp1, thiscinfo->hbrush); - return (LONG)thiscinfo->hbrush; - } - } - - } - break; - } - } - - if(!pOldProc) - return DefWindowProc(hWnd, msg, mp1, mp2); - return CallWindowProc(pOldProc, hWnd, msg, mp1, mp2); -} - -BOOL CALLBACK _containerwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) -{ - ContainerInfo *cinfo; - - cinfo = (ContainerInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); - - switch( msg ) - { - case WM_COMMAND: - case WM_NOTIFY: - _wndproc(hWnd, msg, mp1, mp2); - break; - case WM_LBUTTONDBLCLK: - case WM_CHAR: - { - LV_ITEM lvi; - int iItem; - - if(LOWORD(mp1) == '\t') - { - if(GetAsyncKeyState(VK_SHIFT) & 0x8000) - _shift_focus_back(hWnd); - else - _shift_focus(hWnd); - return FALSE; - } - - if(msg == WM_CHAR && (char)mp1 != '\r') - break; - - iItem = ListView_GetNextItem(hWnd, -1, LVNI_FOCUSED); - - memset(&lvi, 0, sizeof(LV_ITEM)); - - if(iItem > -1) - { - lvi.iItem = iItem; - lvi.mask = LVIF_PARAM; - - ListView_GetItem(hWnd, &lvi); - } - - { - SignalHandler *tmp = Root; - - while(tmp) - { - 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); - tmp = NULL; - } - if(tmp) - tmp = tmp->next; - } - } - } - break; - case WM_CONTEXTMENU: - { - SignalHandler *tmp = Root; - - while(tmp) - { - if(tmp->message == NM_RCLICK && tmp->window == hWnd) - { - int (*containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction; - LONG x,y; - LV_ITEM lvi; - int iItem; - LVHITTESTINFO lhi; - - dw_pointer_query_pos(&x, &y); - - lhi.pt.x = x; - lhi.pt.y = y; - - MapWindowPoints(HWND_DESKTOP, tmp->window, &lhi.pt, 1); - - iItem = ListView_HitTest(tmp->window, &lhi); - - memset(&lvi, 0, sizeof(LV_ITEM)); - - if(iItem > -1) - { - lvi.iItem = iItem; - lvi.mask = LVIF_PARAM; - - ListView_GetItem(tmp->window, &lvi); - ListView_SetSelectionMark(tmp->window, iItem); - } - - /* 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); - tmp = NULL; - } - if(tmp) - tmp = tmp->next; - } - } - break; - } - - if(!cinfo || !cinfo->pOldProc) - return DefWindowProc(hWnd, msg, mp1, mp2); - return CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); -} - -BOOL CALLBACK _treewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) -{ - ContainerInfo *cinfo; - - cinfo = (ContainerInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); - - switch( msg ) - { - case WM_CHAR: - if(LOWORD(mp1) == '\t') - { - if(GetAsyncKeyState(VK_SHIFT) & 0x8000) - _shift_focus_back(hWnd); - else - _shift_focus(hWnd); - return FALSE; - } - break; - } - - if(!cinfo || !cinfo->pOldProc) - return DefWindowProc(hWnd, msg, mp1, mp2); - return CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); -} - -void _changebox(Box *thisbox, int percent, int type) -{ - int z; - - for(z=0;z<thisbox->count;z++) - { - if(thisbox->items[z].type == TYPEBOX) - { - Box *tmp = (Box*)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA); - _changebox(tmp, percent, type); - } - else - { - if(type == DW_HORZ) - { - if(thisbox->items[z].hsize == SIZEEXPAND) - thisbox->items[z].width = (int)(((float)thisbox->items[z].origwidth) * (((float)percent)/((float)100.0))); - } - else - { - if(thisbox->items[z].vsize == SIZEEXPAND) - thisbox->items[z].height = (int)(((float)thisbox->items[z].origheight) * (((float)percent)/((float)100.0))); - } - } - } -} - -void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y) -{ - if(type == DW_HORZ) - { - int newx = x; - float ratio = (float)percent/(float)100.0; - HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_topleft"); - HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright"); - Box *tmp = (Box *)GetWindowLongPtr(handle1, GWLP_USERDATA); - - newx = (int)((float)newx * ratio) - (SPLITBAR_WIDTH/2); - - ShowWindow(handle1, SW_HIDE); - ShowWindow(handle2, SW_HIDE); - - MoveWindow(handle1, 0, 0, newx, y, FALSE); - _do_resize(tmp, newx - 1, y - 1); - - tmp = (Box *)GetWindowLongPtr(handle2, GWLP_USERDATA); - - newx = x - newx - SPLITBAR_WIDTH; - - MoveWindow(handle2, x - newx, 0, newx, y, FALSE); - _do_resize(tmp, newx - 1, y - 1); - - ShowWindow(handle1, SW_SHOW); - ShowWindow(handle2, SW_SHOW); - - dw_window_set_data(hwnd, "_dw_start", (void *)newx); - } - else - { - int newy = y; - float ratio = (float)(100.0-percent)/(float)100.0; - HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright"); - HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_topleft"); - Box *tmp = (Box *)GetWindowLongPtr(handle1, GWLP_USERDATA); - - newy = (int)((float)newy * ratio) - (SPLITBAR_WIDTH/2); - - ShowWindow(handle1, SW_HIDE); - ShowWindow(handle2, SW_HIDE); - - MoveWindow(handle1, 0, y - newy, x, newy, FALSE); - _do_resize(tmp, x - 1, newy - 1); - - tmp = (Box *)GetWindowLongPtr(handle2, GWLP_USERDATA); - - newy = y - newy - SPLITBAR_WIDTH; - - MoveWindow(handle2, 0, 0, x, newy, FALSE); - _do_resize(tmp, x - 1, newy - 1); - - ShowWindow(handle1, SW_SHOW); - ShowWindow(handle2, SW_SHOW); - - dw_window_set_data(hwnd, "_dw_start", (void *)newy); - } -} - -/* This handles any activity on the splitbars (sizers) */ -BOOL CALLBACK _splitwndproc(HWND hwnd, UINT msg, WPARAM mp1, LPARAM mp2) -{ - float *percent = (float *)dw_window_get_data(hwnd, "_dw_percent"); - int type = (int)dw_window_get_data(hwnd, "_dw_type"); - int start = (int)dw_window_get_data(hwnd, "_dw_start"); - - switch (msg) - { - case WM_ACTIVATE: - case WM_SETFOCUS: - return FALSE; - - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdcPaint; - - BeginPaint(hwnd, &ps); - - if((hdcPaint = GetDC(hwnd)) != NULL) - { - int cx, cy; - HBRUSH oldBrush = SelectObject(hdcPaint, GetSysColorBrush(COLOR_3DFACE)); - HPEN oldPen = SelectObject(hdcPaint, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DFACE))); - - dw_window_get_pos_size(hwnd, NULL, NULL, &cx, &cy); - - if(type == DW_HORZ) - Rectangle(hdcPaint, cx - start - SPLITBAR_WIDTH, 0, cx - start, cy); - else - Rectangle(hdcPaint, 0, start, cx, start + SPLITBAR_WIDTH); - - SelectObject(hdcPaint, oldBrush); - DeleteObject(SelectObject(hdcPaint, oldPen)); - ReleaseDC(hwnd, hdcPaint); - } - EndPaint(hwnd, &ps); - } - break; - case WM_LBUTTONDOWN: - { - SetCapture(hwnd); - break; - } - case WM_LBUTTONUP: - { - if(GetCapture() == hwnd) - ReleaseCapture(); - } - break; - case WM_MOUSEMOVE: - { - if(type == DW_HORZ) - SetCursor(LoadCursor(NULL, IDC_SIZEWE)); - else - SetCursor(LoadCursor(NULL, IDC_SIZENS)); - - if(GetCapture() == hwnd && percent) - { - POINT point; - RECT rect; - static POINT lastpoint; - - GetCursorPos(&point); - GetWindowRect(hwnd, &rect); - - if(memcmp(&point, &lastpoint, sizeof(POINT))) - { - if(PtInRect(&rect, point)) - { - int width = (rect.right - rect.left); - int height = (rect.bottom - rect.top); - - if(type == DW_HORZ) - { - start = point.x - rect.left; - if(width - SPLITBAR_WIDTH > 1 && start < width - SPLITBAR_WIDTH) - *percent = ((float)start / (float)(width - SPLITBAR_WIDTH)) * 100.0; - } - else - { - start = point.y - rect.top; - if(height - SPLITBAR_WIDTH > 1 && start < height - SPLITBAR_WIDTH) - *percent = ((float)start / (float)(height - SPLITBAR_WIDTH)) * 100.0; - } - _handle_splitbar_resize(hwnd, *percent, type, width, height); - } - memcpy(&lastpoint, &point, sizeof(POINT)); - } - } - break; - } - } - return DefWindowProc(hwnd, msg, mp1, mp2); -} - -/* This handles drawing the status text areas */ -BOOL CALLBACK _statuswndproc(HWND hwnd, UINT msg, WPARAM mp1, LPARAM mp2) -{ - switch (msg) - { - case WM_SETTEXT: - { - /* Make sure the control redraws when there is a text change */ - int ret = (int)DefWindowProc(hwnd, msg, mp1, mp2); - - InvalidateRgn(hwnd, NULL, TRUE); - return ret; - } - case WM_PAINT: - { - HDC hdcPaint; - PAINTSTRUCT ps; - RECT rc; - unsigned long cx, cy; - int threadid = dw_thread_id(); - char tempbuf[1024] = ""; - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(hwnd, GWLP_USERDATA); - HFONT hfont = _acquire_font(hwnd, cinfo ? cinfo->fontname : NULL); - HFONT oldfont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); - - dw_window_get_pos_size(hwnd, NULL, NULL, &cx, &cy); - GetWindowText(hwnd, tempbuf, 1024); - - 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); - if(hfont && oldfont) - SelectObject(hdcPaint, oldfont); - if(hfont) - DeleteObject(hfont); - EndPaint(hwnd, &ps); - } - return FALSE; - } - return DefWindowProc(hwnd, msg, mp1, mp2); -} - -/* Function: _BtProc - * Abstract: Subclass procedure for buttons - */ - -BOOL CALLBACK _BtProc(HWND hwnd, ULONG msg, WPARAM mp1, LPARAM mp2) -{ - BubbleButton *bubble; - static int bMouseOver = 0; - POINT point; - RECT rect; - WNDPROC pOldProc; - - bubble = (BubbleButton *)GetWindowLongPtr(hwnd, GWLP_USERDATA); - - if(!bubble) - return DefWindowProc(hwnd, msg, mp1, mp2); - - /* We must save a pointer to the old - * window procedure because if a signal - * handler attached here destroys this - * window it will then be invalid. - */ - pOldProc = bubble->pOldProc; - - switch(msg) - { - case WM_CTLCOLORSTATIC: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORBTN: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORDLG: - _wndproc(hwnd, msg, mp1, mp2); - break; - case WM_SETFOCUS: - _wndproc(hwnd, msg, mp1, mp2); - break; - case WM_LBUTTONUP: - { - SignalHandler *tmp = Root; - - /* Find any callbacks for this function */ - while(tmp) - { - if(tmp->message == WM_COMMAND) - { - int (*clickfunc)(HWND, void *) = tmp->signalfunction; - - /* Make sure it's the right window, and the right ID */ - if(tmp->window == hwnd) - { - if(bubble->checkbox) - in_checkbox_handler = 1; - - clickfunc(tmp->window, tmp->data); - - if(bubble->checkbox) - in_checkbox_handler = 0; - tmp = NULL; - } - } - if(tmp) - tmp= tmp->next; - } - } - break; - case WM_CHAR: - { - /* A button press should also occur for an ENTER or SPACE press - * while the button has the active input focus. - */ - if(LOWORD(mp1) == '\r' || LOWORD(mp1) == ' ') - { - SignalHandler *tmp = Root; - - /* Find any callbacks for this function */ - while(tmp) - { - if(tmp->message == WM_COMMAND) - { - int (*clickfunc)(HWND, void *) = tmp->signalfunction; - - /* Make sure it's the right window, and the right ID */ - if(tmp->window == hwnd) - { - clickfunc(tmp->window, tmp->data); - tmp = NULL; - } - } - if(tmp) - tmp= tmp->next; - } - } - if(LOWORD(mp1) == '\t') - { - if(GetAsyncKeyState(VK_SHIFT) & 0x8000) - _shift_focus_back(hwnd); - else - _shift_focus(hwnd); - return FALSE; - } - } - break; - case WM_KEYDOWN: - if(mp1 == VK_LEFT || mp1 == VK_UP) - _shift_focus_back(hwnd); - if(mp1 == VK_RIGHT || mp1 == VK_DOWN) - _shift_focus(hwnd); - break; - case WM_TIMER: - if (hwndBubble) - { - _free_window_memory(hwndBubble, 0); - DestroyWindow(hwndBubble); - hwndBubble = 0; - KillTimer(hwnd, 1); - } - break; - - case WM_MOUSEMOVE: - GetCursorPos(&point); - GetWindowRect(hwnd, &rect); - - if(PtInRect(&rect, point)) - { - if(hwnd != GetCapture()) - { - SetCapture(hwnd); - } - if(!bMouseOver) - { - bMouseOver = 1; - if(!*bubble->bubbletext) - break; - - if(hwndBubble) - { - _free_window_memory(hwndBubble, 0); - DestroyWindow(hwndBubble); - hwndBubble = 0; - KillTimer(hwndBubbleLast, 1); - } - - if(!hwndBubble) - { - POINTL ptlWork = {0,0}; - ULONG ulColor = DW_CLR_YELLOW; - SIZE size; - HFONT hFont, oldFont = (HFONT)0; - HDC hdc; - RECT rect; - void *oldproc; - - /* Use the WS_EX_TOOLWINDOW extended style - * so the window doesn't get listed in the - * taskbar. - */ - hwndBubble = CreateWindowEx(WS_EX_TOOLWINDOW, - STATICCLASSNAME, - bubble->bubbletext, - BS_TEXT | WS_POPUP | - WS_BORDER | - SS_CENTER, - 0,0,50,20, - HWND_DESKTOP, - NULL, - DWInstance, - NULL); - - dw_window_set_font(hwndBubble, DefaultFont); - dw_window_set_color(hwndBubble, DW_CLR_BLACK, DW_CLR_YELLOW); - - hwndBubbleLast = hwnd; - - SetTimer(hwnd, 1, 3000, NULL); - - hFont = (HFONT)SendMessage(hwndBubble, WM_GETFONT, 0, 0); - - hdc = GetDC(hwndBubble); - - if(hFont) - oldFont = (HFONT)SelectObject(hdc, hFont); - - GetTextExtentPoint32(hdc, bubble->bubbletext, strlen(bubble->bubbletext), &size); - - if(hFont) - SelectObject(hdc, oldFont); - - MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT)&ptlWork, 1); - - GetWindowRect(hwnd, &rect); - - SetWindowPos(hwndBubble, - HWND_TOP, - ptlWork.x, - ptlWork.y + (rect.bottom-rect.top) + 1, - size.cx + 8, - size.cy + 2, - SWP_NOACTIVATE | SWP_SHOWWINDOW); - - ReleaseDC(hwndBubble, hdc); - } - } - } - else{ - /* Calling ReleaseCapture in Win95 also causes WM_CAPTURECHANGED - * to be sent. Be sure to account for that. - */ - ReleaseCapture(); - - if(bMouseOver) - { - bMouseOver = 0; - _free_window_memory(hwndBubble, 0); - DestroyWindow(hwndBubble); - hwndBubble = 0; - KillTimer(hwndBubbleLast, 1); - } - } - break; - case WM_CAPTURECHANGED: - /* This message means we are losing the capture for some reason - * Either because we intentionally lost it or another window - * stole it - */ - if(bMouseOver) - { - bMouseOver = 0; - _free_window_memory(hwndBubble, 0); - DestroyWindow(hwndBubble); - hwndBubble = 0; - KillTimer(hwndBubbleLast, 1); - } - break; - } - - if(!pOldProc) - return DefWindowProc(hwnd, msg, mp1, mp2); - return CallWindowProc(pOldProc, hwnd, msg, mp1, mp2); -} - -/* This function recalculates a notebook page for example - * during switching of notebook pages. - */ -void _resize_notebook_page(HWND handle, int pageid) -{ - RECT rect; - NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); - - if(array && array[pageid]) - { - Box *box = (Box *)GetWindowLongPtr(array[pageid]->hwnd, GWLP_USERDATA); - - GetClientRect(handle,&rect); - TabCtrl_AdjustRect(handle,FALSE,&rect); - MoveWindow(array[pageid]->hwnd, rect.left, rect.top, - rect.right - rect.left, rect.bottom-rect.top, TRUE); - if(box && box->count) - { - ShowWindow(box->items[0].hwnd, SW_HIDE); - _do_resize(box, rect.right - rect.left, rect.bottom - rect.top); - ShowWindow(box->items[0].hwnd, SW_SHOW); - } - - ShowWindow(array[pageid]->hwnd, SW_SHOWNORMAL); - } -} - -/* - * Initializes the Dynamic Windows engine. - * Parameters: - * newthread: True if this is the only thread. - * False if there is already a message loop running. - */ -int API dw_init(int newthread, int argc, char *argv[]) -{ - WNDCLASS wc; - int z; - INITCOMMONCONTROLSEX icc; - - icc.dwSize = sizeof(INITCOMMONCONTROLSEX); - icc.dwICC = ICC_WIN95_CLASSES; - - InitCommonControlsEx(&icc); - - memset(lookup, 0, sizeof(HICON) * ICON_INDEX_LIMIT); - - /* Register the generic Dynamic Windows class */ - memset(&wc, 0, sizeof(WNDCLASS)); - wc.style = CS_DBLCLKS; - wc.lpfnWndProc = (WNDPROC)_wndproc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 32; - wc.hbrBackground = NULL; - wc.lpszMenuName = NULL; - wc.lpszClassName = ClassName; - - RegisterClass(&wc); - - /* Register the splitbar control */ - memset(&wc, 0, sizeof(WNDCLASS)); - wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = (WNDPROC)_splitwndproc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hbrBackground = NULL; - wc.lpszMenuName = NULL; - wc.lpszClassName = SplitbarClassName; - - RegisterClass(&wc); - - /* Register a frame control like on OS/2 */ - memset(&wc, 0, sizeof(WNDCLASS)); - wc.style = CS_DBLCLKS; - wc.lpfnWndProc = (WNDPROC)_framewndproc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 32; - wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_3DFACE); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.lpszMenuName = NULL; - wc.lpszClassName = FRAMECLASSNAME; - - RegisterClass(&wc); - - /* Create a set of brushes using the default OS/2 and DOS colors */ - for(z=0;z<18;z++) - _colors[z] = CreateSolidBrush(RGB(_red[z],_green[z],_blue[z])); - - /* Register an Object Windows class like OS/2 and Win2k+ - * so similar functionality can be used on earlier releases - * of Windows. - */ - memset(&wc, 0, sizeof(WNDCLASS)); - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)_wndproc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hbrBackground = NULL; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.lpszMenuName = NULL; - wc.lpszClassName = ObjectClassName; - - RegisterClass(&wc); - - /* Since Windows 95/98/NT don't have a HWND_OBJECT class - * also known as a input only window, I will create a - * temporary window that isn't visible and really does nothing - * except temporarily hold the child windows before they are - * packed into their correct parent. - */ - - DW_HWND_OBJECT = CreateWindow(ObjectClassName, "", 0, 0, 0, - 0, 0, HWND_DESKTOP, NULL, DWInstance, NULL); - - if(!DW_HWND_OBJECT) - { - dw_messagebox("Dynamic Windows", DW_MB_OK|DW_MB_ERROR, "Could not initialize the object window. error code %d", GetLastError()); - exit(1); - } - - /* We need the version to check capability like up-down controls */ - dwVersion = GetVersion(); - dwComctlVer = GetDllVersion(TEXT("comctl32.dll")); - - for(z=0;z<THREAD_LIMIT;z++) - { - _foreground[z] = RGB(128,128,128); - _background[z] = DW_RGB_TRANSPARENT; - _hPen[z] = CreatePen(PS_SOLID, 1, _foreground[z]); - _hBrush[z] = CreateSolidBrush(_foreground[z]); - } - - return 0; -} - -/* - * Runs a message loop for Dynamic Windows. - */ -void API dw_main(void) -{ - MSG msg; - - _dwtid = dw_thread_id(); - - while(GetMessage(&msg, NULL, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } -} - -/* - * Runs a message loop for Dynamic Windows, for a period of milliseconds. - * Parameters: - * milliseconds: Number of milliseconds to run the loop for. - */ -void API dw_main_sleep(int milliseconds) -{ - MSG msg; - double start = (double)clock(); - - while(((clock() - start) / (CLOCKS_PER_SEC/1000)) <= milliseconds) - { - if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) - { - GetMessage(&msg, NULL, 0, 0); - TranslateMessage(&msg); - DispatchMessage(&msg); - } - else - Sleep(1); - } -} - -/* - * Processes a single message iteration and returns. - */ -void API dw_main_iteration(void) -{ - MSG msg; - - _dwtid = dw_thread_id(); - - if(GetMessage(&msg, NULL, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } -} - -/* - * Free's memory allocated by dynamic windows. - * Parameters: - * ptr: Pointer to dynamic windows allocated - * memory to be free()'d. - */ -void API dw_free(void *ptr) -{ - free(ptr); -} - -/* - * Allocates and initializes a dialog struct. - * Parameters: - * data: User defined data to be passed to functions. - */ -DWDialog * API dw_dialog_new(void *data) -{ - DWDialog *tmp = malloc(sizeof(DWDialog)); - - tmp->eve = dw_event_new(); - dw_event_reset(tmp->eve); - tmp->data = data; - tmp->done = FALSE; - tmp->result = NULL; - - return tmp; -} - -/* - * Accepts a dialog struct and returns the given data to the - * initial called of dw_dialog_wait(). - * Parameters: - * dialog: Pointer to a dialog struct aquired by dw_dialog_new). - * result: Data to be returned by dw_dialog_wait(). - */ -int API dw_dialog_dismiss(DWDialog *dialog, void *result) -{ - dialog->result = result; - dw_event_post(dialog->eve); - dialog->done = TRUE; - return 0; -} - -/* - * Accepts a dialog struct waits for dw_dialog_dismiss() to be - * called by a signal handler with the given dialog struct. - * Parameters: - * dialog: Pointer to a dialog struct aquired by dw_dialog_new). - */ -void * API dw_dialog_wait(DWDialog *dialog) -{ - MSG msg; - void *tmp; - - while (GetMessage(&msg,NULL,0,0)) - { - if(msg.hwnd == NULL && msg.message == WM_TIMER) - _wndproc(msg.hwnd, msg.message, msg.wParam, msg.lParam); - TranslateMessage(&msg); - DispatchMessage(&msg); - if(dialog->done) - break; - } - dw_event_close(&dialog->eve); - tmp = dialog->result; - free(dialog); - return tmp; -} - -/* - * Displays a Message Box with given text and title.. - * Parameters: - * title: The title of the message box. - * format: printf style format string. - * ...: Additional variables for use in the format. - */ -int API dw_messagebox(char *title, int flags, char *format, ...) -{ - va_list args; - char outbuf[256]; - int rc; - - va_start(args, format); - vsprintf(outbuf, format, args); - va_end(args); - - rc = MessageBox(HWND_DESKTOP, outbuf, title, flags); - if(rc == IDOK) - return DW_MB_RETURN_OK; - else if(rc == IDYES) - return DW_MB_RETURN_YES; - else if(rc == IDNO) - return DW_MB_RETURN_NO; - else if(rc == IDCANCEL) - return DW_MB_RETURN_CANCEL; - else return 0; -} - -/* - * Minimizes or Iconifies a top-level window. - * Parameters: - * handle: The window handle to minimize. - */ -int API dw_window_minimize(HWND handle) -{ - return ShowWindow(handle, SW_MINIMIZE); -} - -/* - * Makes the window topmost. - * Parameters: - * handle: The window handle to make topmost. - */ -int API dw_window_raise(HWND handle) -{ - return SetWindowPos(handle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); -} - -/* - * Makes the window bottommost. - * Parameters: - * handle: The window handle to make bottommost. - */ -int API dw_window_lower(HWND handle) -{ - return SetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); -} - -/* - * Makes the window visible. - * Parameters: - * handle: The window handle to make visible. - */ -int API dw_window_show(HWND handle) -{ - int rc = ShowWindow(handle, SW_SHOW); - SetFocus(handle); - _initial_focus(handle); - return rc; -} - -/* - * Makes the window invisible. - * Parameters: - * handle: The window handle to make visible. - */ -int API dw_window_hide(HWND handle) -{ - return ShowWindow(handle, SW_HIDE); -} - -/* - * Destroys a window and all of it's children. - * Parameters: - * handle: The window handle to destroy. - */ -int API dw_window_destroy(HWND handle) -{ - HWND parent = GetParent(handle); - Box *thisbox = (Box *)GetWindowLongPtr(parent, GWLP_USERDATA); -#ifndef WINNT_COMPAT - HMENU menu = GetMenu(handle); - - if(menu) - _free_menu_data(menu); -#endif - - if(parent != HWND_DESKTOP && thisbox && thisbox->count) - { - int z, index = -1; - Item *tmpitem, *thisitem = thisbox->items; - - for(z=0;z<thisbox->count;z++) - { - if(thisitem[z].hwnd == handle) - index = z; - } - - if(index == -1) - return 0; - - tmpitem = malloc(sizeof(Item)*(thisbox->count-1)); - - /* Copy all but the current entry to the new list */ - for(z=0;z<index;z++) - { - tmpitem[z] = thisitem[z]; - } - for(z=index+1;z<thisbox->count;z++) - { - tmpitem[z-1] = thisitem[z]; - } - - thisbox->items = tmpitem; - free(thisitem); - thisbox->count--; - _free_window_memory(handle, 0); - EnumChildWindows(handle, _free_window_memory, 0); - } - return DestroyWindow(handle); -} - -/* Causes entire window to be invalidated and redrawn. - * Parameters: - * handle: Toplevel window handle to be redrawn. - */ -void API dw_window_redraw(HWND handle) -{ - Box *mybox = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA); - - if(mybox) - { - RECT rect; - int istoplevel = (GetParent(handle) == HWND_DESKTOP); - - GetClientRect(handle, &rect); - - ShowWindow(istoplevel ? mybox->items[0].hwnd : handle, SW_HIDE); - _do_resize(mybox, rect.right - rect.left, rect.bottom - rect.top); - ShowWindow(istoplevel ? mybox->items[0].hwnd : handle, SW_SHOW); - } -} - -int instring(char *text, char *buffer) -{ - int z, len = strlen(text), buflen = strlen(buffer); - - if(buflen > len) - { - for(z=0;z<=(buflen-len);z++) - { - if(memcmp(text, &buffer[z], len) == 0) - return z; - } - } - return 0; -} - -/* - * Changes a window's parent to newparent. - * Parameters: - * handle: The window handle to destroy. - * newparent: The window's new parent window. - */ -void API dw_window_reparent(HWND handle, HWND newparent) -{ - SetParent(handle, newparent); -} - -HFONT _acquire_font(HWND handle, char *fontname) -{ - HFONT hfont = 0; - - if(fontname != DefaultFont && fontname[0]) - { - int Italic, Bold; - char *myFontName; - int z, size = 9; - LOGFONT lf; -#if 0 - HDC hDC = GetDC(handle); -#endif - for(z=0;z<strlen(fontname);z++) - { - if(fontname[z]=='.') - break; - } - size = atoi(fontname) + 5; - Italic = instring(" Italic", &fontname[z+1]); - Bold = instring(" Bold", &fontname[z+1]); -#if 0 - lf.lfHeight = -MulDiv(size, GetDeviceCaps(hDC, LOGPIXELSY), 72); -#endif - lf.lfHeight = size; - lf.lfWidth = 0; - lf.lfEscapement = 0; - lf.lfOrientation = 0; - lf.lfItalic = Italic ? TRUE : FALSE; - lf.lfUnderline = 0; - lf.lfStrikeOut = 0; - lf.lfWeight = Bold ? FW_BOLD : FW_NORMAL; - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfOutPrecision = 0; - lf.lfClipPrecision = 0; - lf.lfQuality = DEFAULT_QUALITY; - lf.lfPitchAndFamily = DEFAULT_PITCH | FW_DONTCARE; - /* - * remove any font modifiers - */ - myFontName = strdup(&fontname[z+1]); - if(Italic) - myFontName[Italic] = 0; - if(Bold) - myFontName[Bold] = 0; - strcpy(lf.lfFaceName, myFontName); - free(myFontName); - - hfont = CreateFontIndirect(&lf); -#if 0 - ReleaseDC(handle, hDC); -#endif - } - if(!hfont) - hfont = GetStockObject(DEFAULT_GUI_FONT); - return hfont; -} - -/* - * Sets the font used by a specified window (widget) handle. - * Parameters: - * handle: The window (widget) handle. - * fontname: Name and size of the font in the form "size.fontname" - */ -int API dw_window_set_font(HWND handle, char *fontname) -{ - HFONT oldfont = (HFONT)SendMessage(handle, WM_GETFONT, 0, 0); - HFONT hfont = _acquire_font(handle, fontname); - ColorInfo *cinfo; - - cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - - if(fontname) - { - if(cinfo) - { - strcpy(cinfo->fontname, fontname); - if(!oldfont) - oldfont = cinfo->hfont; - cinfo->hfont = hfont; - } - else - { - cinfo = calloc(1, sizeof(ColorInfo)); - cinfo->fore = cinfo->back = -1; - - strcpy(cinfo->fontname, fontname); - - cinfo->pOldProc = SubclassWindow(handle, _colorwndproc); - SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo); - } - } - SendMessage(handle, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE); - if(oldfont) - DeleteObject(oldfont); - return 0; -} - -/* - * Sets the colors used by a specified window (widget) handle. - * Parameters: - * handle: The window (widget) handle. - * fore: Foreground color in RGB format. - * back: Background color in RGB format. - */ -int API dw_window_set_color(HWND handle, ULONG fore, ULONG back) -{ - ColorInfo *cinfo; - char tmpbuf[100]; - - cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW))==0) - { - fore = _internal_color(fore); - back = _internal_color(back); - - ListView_SetTextColor(handle, RGB(DW_RED_VALUE(fore), - DW_GREEN_VALUE(fore), - DW_BLUE_VALUE(fore))); - ListView_SetTextBkColor(handle, RGB(DW_RED_VALUE(back), - DW_GREEN_VALUE(back), - DW_BLUE_VALUE(back))); - ListView_SetBkColor(handle, RGB(DW_RED_VALUE(back), - DW_GREEN_VALUE(back), - DW_BLUE_VALUE(back))); - InvalidateRgn(handle, NULL, TRUE); - return TRUE; - } - - if(cinfo) - { - cinfo->fore = fore; - cinfo->back = back; - } - else - { - cinfo = calloc(1, sizeof(ColorInfo)); - - cinfo->fore = fore; - cinfo->back = back; - - cinfo->pOldProc = SubclassWindow(handle, _colorwndproc); - SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo); - } - InvalidateRgn(handle, NULL, TRUE); - return TRUE; -} - -/* - * Sets the font used by a specified window (widget) handle. - * Parameters: - * handle: The window (widget) handle. - * border: Size of the window border in pixels. - */ -int API dw_window_set_border(HWND handle, int border) -{ - return 0; -} - -/* - * Captures the mouse input to this window. - * Parameters: - * handle: Handle to receive mouse input. - */ -void API dw_window_capture(HWND handle) -{ - SetCapture(handle); -} - -/* - * Releases previous mouse capture. - */ -void API dw_window_release(void) -{ - ReleaseCapture(); -} - -/* - * Changes the appearance of the mouse pointer. - * Parameters: - * handle: Handle to widget for which to change. - * cursortype: ID of the pointer you want. - */ -void API dw_window_pointer(HWND handle, int pointertype) -{ -/* - if(pointertype == DW_POINTER_ARROW) - SetClassLong( handle, GCL_HCURSOR, LoadCursor( NULL, IDC_ARROW)); - else if(pointertype == DW_POINTER_CLOCK) - SetClassLong( handle, GCL_HCURSOR, LoadCursor( NULL, IDC_WAIT)); - else -*/ - SetCursor(pointertype < 65536 ? LoadCursor(NULL, MAKEINTRESOURCE(pointertype)) : (HCURSOR)pointertype); -} - -/* - * Create a new Window Frame. - * Parameters: - * owner: The Owner's window handle or HWND_DESKTOP. - * title: The Window title. - * flStyle: Style flags, see the DW reference. - */ -HWND API dw_window_new(HWND hwndOwner, char *title, ULONG flStyle) -{ - HWND hwndframe; - Box *newbox = calloc(sizeof(Box), 1); - ULONG flStyleEx = 0; - - newbox->pad = 0; - newbox->type = DW_VERT; - newbox->count = 0; - newbox->cinfo.fore = newbox->cinfo.back = -1; - - if(hwndOwner) - flStyleEx |= WS_EX_MDICHILD; - - if(!(flStyle & WS_CAPTION)) - flStyle |= WS_POPUPWINDOW; - - if(flStyle & DW_FCF_TASKLIST) - { - ULONG newflags = (flStyle | WS_CLIPCHILDREN) & ~DW_FCF_TASKLIST; - - hwndframe = CreateWindowEx(flStyleEx, ClassName, title, newflags, CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner, NULL, DWInstance, NULL); - } - else - { - flStyleEx |= WS_EX_TOOLWINDOW; - - hwndframe = CreateWindowEx(flStyleEx, ClassName, title, flStyle | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner, NULL, DWInstance, NULL); - } - SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox); - -#if 0 - if(hwndOwner) - SetParent(hwndframe, hwndOwner); -#endif - - return hwndframe; -} - -/* - * Create a new Box to be packed. - * Parameters: - * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). - * pad: Number of pixels to pad around the box. - */ -HWND API dw_box_new(int type, int pad) -{ - Box *newbox = calloc(sizeof(Box), 1); - HWND hwndframe; - - newbox->pad = pad; - newbox->type = type; - newbox->count = 0; - newbox->grouphwnd = (HWND)NULL; - newbox->cinfo.fore = newbox->cinfo.back = -1; - - hwndframe = CreateWindow(FRAMECLASSNAME, - "", - WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - NULL, - DWInstance, - NULL); - - newbox->cinfo.pOldProc = SubclassWindow(hwndframe, _colorwndproc); - newbox->cinfo.fore = newbox->cinfo.back = -1; - - SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox); - return hwndframe; -} - -/* - * Create a new Group Box to be packed. - * Parameters: - * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). - * pad: Number of pixels to pad around the box. - * title: Text to be displayined in the group outline. - */ -HWND API dw_groupbox_new(int type, int pad, char *title) -{ - Box *newbox = calloc(sizeof(Box), 1); - HWND hwndframe; - - newbox->pad = pad; - newbox->type = type; - newbox->count = 0; - newbox->cinfo.fore = newbox->cinfo.back = -1; - - hwndframe = CreateWindow(FRAMECLASSNAME, - "", - WS_VISIBLE | WS_CHILD, - 0,0,2000,1000, - DW_HWND_OBJECT, - NULL, - DWInstance, - NULL); - - newbox->grouphwnd = CreateWindow(BUTTONCLASSNAME, - title, - WS_CHILD | BS_GROUPBOX | - WS_VISIBLE | WS_CLIPCHILDREN, - 0,0,2000,1000, - hwndframe, - NULL, - DWInstance, - NULL); - - SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox); - dw_window_set_font(newbox->grouphwnd, DefaultFont); - return hwndframe; -} - -/* - * Create a new MDI Frame to be packed. - * Parameters: - * id: An ID to be used with dw_window_from_id or 0L. - */ -HWND API dw_mdi_new(unsigned long id) -{ - CLIENTCREATESTRUCT ccs; - HWND hwndframe; - - ccs.hWindowMenu = NULL; - ccs.idFirstChild = 0; - - hwndframe = CreateWindow("MDICLIENT", - "", - WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - &ccs); - return hwndframe; -} - -/* - * Create a bitmap object to be packed. - * Parameters: - * id: An ID to be used with dw_window_from_id or 0L. - */ -HWND API dw_bitmap_new(ULONG id) -{ - return CreateWindow(STATICCLASSNAME, - "", - SS_BITMAP | WS_VISIBLE | - WS_CHILD | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); -} - -/* - * Create a notebook object to be packed. - * Parameters: - * id: An ID to be used for getting the resource from the - * resource file. - */ -HWND API dw_notebook_new(ULONG id, int top) -{ - ULONG flags = 0; - HWND tmp; - NotebookPage **array = calloc(256, sizeof(NotebookPage *)); - - if(!top) - flags = TCS_BOTTOM; - - tmp = CreateWindow(WC_TABCONTROL, - "", - WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - dw_window_set_data(tmp, "_dw_array", (void *)array); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Create a menu object to be popped up. - * Parameters: - * id: An ID to be used for getting the resource from the - * resource file. - */ -HMENUI API dw_menu_new(ULONG id) -{ - return (HMENUI)CreatePopupMenu(); -} - -/* - * Create a menubar on a window. - * Parameters: - * location: Handle of a window frame to be attached to. - */ -HMENUI API dw_menubar_new(HWND location) -{ - HMENUI tmp; - - tmp = (HMENUI)CreateMenu(); - -#ifndef WINNT_COMPAT - { - MENUINFO mi; - - mi.cbSize = sizeof(MENUINFO); - mi.fMask = MIM_MENUDATA; - mi.dwMenuData = (ULONG_PTR)1; - - SetMenuInfo((HMENU)tmp, &mi); - } -#endif - - dw_window_set_data(location, "_dw_menu", (void *)tmp); - - SetMenu(location, (HMENU)tmp); - return location; -} - -/* - * Destroys a menu created with dw_menubar_new or dw_menu_new. - * Parameters: - * menu: Handle of a menu. - */ -void API dw_menu_destroy(HMENUI *menu) -{ - if(menu) - { - HMENU mymenu = (HMENU)*menu; - - if(IsWindow((HWND)mymenu) && !IsMenu(mymenu)) - mymenu = (HMENU)dw_window_get_data((HWND)mymenu, "_dw_menu"); - if(IsMenu(mymenu)) - DestroyMenu(mymenu); - } -} - -/* - * Adds a menuitem or submenu to an existing menu. - * Parameters: - * menu: The handle the the existing menu. - * title: The title text on the menu item to be added. - * id: An ID to be used for message passing. - * end: If TRUE memu is positioned at the end of the menu. - * check: If TRUE menu is "check"able. - * flags: Extended attributes to set on the menu. - * submenu: Handle to an existing menu to be a submenu or NULL. - */ -HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu) -{ - MENUITEMINFO mii; - HMENU mymenu = (HMENU)menux; -#ifndef WINNT_COMPAT - char buffer[15]; -#endif - - if(IsWindow(menux) && !IsMenu(mymenu)) - mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu"); - - mii.cbSize = sizeof(MENUITEMINFO); - mii.fMask = MIIM_ID | MIIM_SUBMENU | MIIM_TYPE; - - /* Convert from OS/2 style accellerators to Win32 style */ - if(title) - { - char *tmp = title; - - while(*tmp) - { - if(*tmp == '~') - *tmp = '&'; - tmp++; - } - } - - if(title && *title) - mii.fType = MFT_STRING; - else - mii.fType = MFT_SEPARATOR; - - mii.wID = id; - if(IsMenu((HMENU)submenu)) - mii.hSubMenu = (HMENU)submenu; - else - mii.hSubMenu = 0; - mii.dwTypeData = title; - mii.cch = strlen(title); - - InsertMenuItem(mymenu, 65535, TRUE, &mii); - -#ifndef WINNT_COMPAT - sprintf(buffer, "_dw_id%d", id); - dw_window_set_data(DW_HWND_OBJECT, buffer, (void *)mymenu); - - /* According to the docs this will only work on Win2k/98 and above */ - if(submenu) - { - MENUINFO mi; - - mi.cbSize = sizeof(MENUINFO); - mi.fMask = MIM_MENUDATA; - mi.dwMenuData = (ULONG_PTR)mymenu; - - SetMenuInfo((HMENU)submenu, &mi); - } -#endif - - if(IsWindow(menux) && !IsMenu((HMENU)menux)) - DrawMenuBar(menux); - return (HWND)id; -} - -/* - * Sets the state of a menu item check. - * Parameters: - * menu: The handle the the existing menu. - * id: Menuitem id. - * check: TRUE for checked FALSE for not checked. - */ -void API dw_menu_item_set_check(HMENUI menux, unsigned long id, int check) -{ - MENUITEMINFO mii; - HMENU mymenu = (HMENU)menux; - - if(IsWindow(menux) && !IsMenu(mymenu)) - mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu"); - - mii.cbSize = sizeof(MENUITEMINFO); - mii.fMask = MIIM_STATE; - if(check) - mii.fState = MFS_CHECKED; - else - mii.fState = MFS_UNCHECKED; - SetMenuItemInfo(mymenu, id, FALSE, &mii); -} - -/* - * Pops up a context menu at given x and y coordinates. - * Parameters: - * menu: The handle the the existing menu. - * parent: Handle to the window initiating the popup. - * x: X coordinate. - * y: Y coordinate. - */ -void API dw_menu_popup(HMENUI *menu, HWND parent, int x, int y) -{ - if(menu) - { - HMENU mymenu = (HMENU)*menu; - - if(IsWindow(*menu) && !IsMenu(mymenu)) - mymenu = (HMENU)dw_window_get_data(*menu, "_dw_menu"); - - popup = parent; - TrackPopupMenu(mymenu, 0, x, y, 0, parent, NULL); - PostMessage(DW_HWND_OBJECT, WM_USER+5, (LPARAM)mymenu, 0); - } -} - - -/* - * Create a container object to be packed. - * Parameters: - * id: An ID to be used for getting the resource from the - * resource file. - */ -HWND API dw_container_new(ULONG id, int multi) -{ - HWND tmp = CreateWindow(WC_LISTVIEW, - "", - WS_VISIBLE | WS_CHILD | - (multi ? 0 : LVS_SINGLESEL) | - LVS_REPORT | LVS_SHOWSELALWAYS | - LVS_SHAREIMAGELISTS | WS_BORDER | - WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); - - if(!cinfo) - { - DestroyWindow(tmp); - return NULL; - } - - cinfo->pOldProc = (WNDPROC)SubclassWindow(tmp, _containerwndproc); - cinfo->cinfo.fore = cinfo->cinfo.back = -1; - - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Create a tree object to be packed. - * Parameters: - * id: An ID to be used for getting the resource from the - * resource file. - */ -HWND API dw_tree_new(ULONG id) -{ - HWND tmp = CreateWindow(WC_TREEVIEW, - "", - WS_VISIBLE | WS_CHILD | - TVS_HASLINES | TVS_SHOWSELALWAYS | - TVS_HASBUTTONS | TVS_LINESATROOT | - WS_BORDER | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); - TreeView_SetItemHeight(tmp, 16); - - if(!cinfo) - { - DestroyWindow(tmp); - return NULL; - } - - cinfo->pOldProc = (WNDPROC)SubclassWindow(tmp, _treewndproc); - cinfo->cinfo.fore = cinfo->cinfo.back = -1; - - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Returns the current X and Y coordinates of the mouse pointer. - * Parameters: - * x: Pointer to variable to store X coordinate. - * y: Pointer to variable to store Y coordinate. - */ -void API dw_pointer_query_pos(long *x, long *y) -{ - POINT ptl; - - GetCursorPos(&ptl); - if(x && y) - { - *x = ptl.x; - *y = ptl.y; - } -} - -/* - * Sets the X and Y coordinates of the mouse pointer. - * Parameters: - * x: X coordinate. - * y: Y coordinate. - */ -void API dw_pointer_set_pos(long x, long y) -{ - SetCursorPos(x, y); -} - -/* - * Create a new static text window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_text_new(char *text, ULONG id) -{ - HWND tmp = CreateWindow(STATICCLASSNAME, - text, - BS_TEXT | WS_VISIBLE | - WS_CHILD | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Create a new status text window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_status_text_new(char *text, ULONG id) -{ - HWND tmp = CreateWindow(ObjectClassName, - text, - BS_TEXT | WS_VISIBLE | - WS_CHILD | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - dw_window_set_font(tmp, DefaultFont); - SubclassWindow(tmp, _statuswndproc); - return tmp; -} - -/* - * Create a new Multiline Editbox window (widget) to be packed. - * Parameters: - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_mle_new(ULONG id) -{ - - HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, - EDITCLASSNAME, - "", - WS_VISIBLE | WS_BORDER | - WS_VSCROLL | ES_MULTILINE | - ES_WANTRETURN | WS_CHILD | - WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); - - if(!cinfo) - { - DestroyWindow(tmp); - return NULL; - } - - cinfo->pOldProc = (WNDPROC)SubclassWindow(tmp, _treewndproc); - cinfo->cinfo.fore = cinfo->cinfo.back = -1; - - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Create a new Entryfield window (widget) to be packed. - * Parameters: - * text: The default text to be in the entryfield widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_entryfield_new(char *text, ULONG id) -{ - HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, - EDITCLASSNAME, - text, - ES_WANTRETURN | WS_CHILD | - WS_BORDER | ES_AUTOHSCROLL | - WS_VISIBLE | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); - - cinfo->back = cinfo->fore = -1; - - cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc); - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Create a new Entryfield passwird window (widget) to be packed. - * Parameters: - * text: The default text to be in the entryfield widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_entryfield_password_new(char *text, ULONG id) -{ - HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, - EDITCLASSNAME, - text, - ES_WANTRETURN | WS_CHILD | - ES_PASSWORD | WS_BORDER | WS_VISIBLE | - ES_AUTOHSCROLL | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); - - cinfo->back = cinfo->fore = -1; - - cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc); - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -BOOL CALLBACK _subclass_child(HWND handle, LPARAM lp) -{ - ColorInfo *cinfo = (ColorInfo *)lp; - - if(cinfo) - { - cinfo->buddy = handle; - cinfo->pOldProc = (WNDPROC)SubclassWindow(handle, _colorwndproc); - SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo); - } - return FALSE; -} - -/* - * Create a new Combobox window (widget) to be packed. - * Parameters: - * text: The default text to be in the combpbox widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_combobox_new(char *text, ULONG id) -{ - HWND tmp = CreateWindow(COMBOBOXCLASSNAME, - text, - WS_CHILD | CBS_DROPDOWN | WS_VSCROLL | - WS_CLIPCHILDREN | CBS_AUTOHSCROLL | WS_VISIBLE, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - ColorInfo *cinfo = (ColorInfo *)calloc(1, sizeof(ColorInfo)); - ColorInfo *cinfo2 = (ColorInfo *)calloc(1, sizeof(ColorInfo)); - - if(!cinfo || !cinfo2) - { - if(cinfo) - free(cinfo); - if(cinfo2) - free(cinfo2); - DestroyWindow(tmp); - return NULL; - } - - cinfo2->fore = cinfo->fore = -1; - cinfo2->back = cinfo->back = -1; - cinfo2->combo = cinfo->combo = tmp; - EnumChildWindows(tmp, _subclass_child, (LPARAM)cinfo2); - - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - dw_window_set_font(tmp, DefaultFont); - SetWindowText(tmp, text); - return tmp; -} - -/* - * Create a new button window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_button_new(char *text, ULONG id) -{ - BubbleButton *bubble = calloc(1, sizeof(BubbleButton)); - - HWND tmp = CreateWindow(BUTTONCLASSNAME, - text, - WS_CHILD | BS_PUSHBUTTON | - WS_VISIBLE | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - - bubble->id = id; - bubble->bubbletext[0] = '\0'; - bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); - - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Create a new bitmap button window (widget) to be packed. - * Parameters: - * text: Bubble help text to be displayed. - * id: An ID of a bitmap in the resource file. - */ -HWND API dw_bitmapbutton_new(char *text, ULONG id) -{ - HWND tmp; - BubbleButton *bubble = calloc(1, sizeof(BubbleButton)); - HBITMAP hbitmap = LoadBitmap(DWInstance, MAKEINTRESOURCE(id)); - - tmp = CreateWindow(BUTTONCLASSNAME, - "", - WS_CHILD | BS_PUSHBUTTON | - BS_BITMAP | WS_CLIPCHILDREN | - WS_VISIBLE, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - - bubble->id = id; - strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1); - bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0'; - bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); - - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble); - - SendMessage(tmp, BM_SETIMAGE, - (WPARAM) IMAGE_BITMAP, - (LPARAM) hbitmap); - return tmp; -} - -/* - * Create a new bitmap button window (widget) to be packed from a file. - * Parameters: - * text: Bubble help text to be displayed. - * id: An ID to be used with dw_window_from_id() or 0L. - * filename: Name of the file, omit extention to have - * DW pick the appropriate file extension. - * (BMP on OS/2 or Windows, XPM on Unix) - */ -HWND dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename) -{ - HWND tmp; - BubbleButton *bubble; - HBITMAP hbitmap = 0; - char *file = malloc(strlen(filename) + 5); - - if(!file || !(bubble = calloc(1, sizeof(BubbleButton)))) - { - if(file) - free(file); - return 0; - } - - tmp = CreateWindow(BUTTONCLASSNAME, - "", - WS_CHILD | BS_PUSHBUTTON | - BS_BITMAP | WS_CLIPCHILDREN | - WS_VISIBLE, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - - bubble->id = id; - strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1); - bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0'; - bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); - - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble); - - strcpy(file, filename); - - /* check if we can read from this file (it exists and read permission) */ - if(access(file, 04) == 0) - hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); - else - { - /* Try with .bmp extention */ - strcat(file, ".bmp"); - if(access(file, 04) == 0) - hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); - } - - - if(hbitmap) - SendMessage(tmp, BM_SETIMAGE, - (WPARAM) IMAGE_BITMAP, - (LPARAM) hbitmap); - free(file); - return tmp; -} - -/* - * Create a new spinbutton window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_spinbutton_new(char *text, ULONG id) -{ - ULONG *data = malloc(sizeof(ULONG)); - HWND buddy = CreateWindowEx(WS_EX_CLIENTEDGE, - EDITCLASSNAME, - text, - WS_CHILD | WS_BORDER | WS_VISIBLE | - ES_NUMBER | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - NULL, - DWInstance, - NULL); - HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, - UPDOWN_CLASS, - NULL, - WS_CHILD | UDS_ALIGNRIGHT | WS_BORDER | - UDS_ARROWKEYS | UDS_SETBUDDYINT | - UDS_WRAP | UDS_NOTHOUSANDS | WS_VISIBLE, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); - - SendMessage(tmp, UDM_SETBUDDY, (WPARAM)buddy, 0); - cinfo->back = cinfo->fore = -1; - cinfo->buddy = tmp; - - cinfo->pOldProc = SubclassWindow(buddy, _colorwndproc); - SetWindowLongPtr(buddy, GWLP_USERDATA, (LONG_PTR)cinfo); - - cinfo = calloc(1, sizeof(ColorInfo)); - cinfo->buddy = buddy; - cinfo->pOldProc = SubclassWindow(tmp, _spinnerwndproc); - - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - dw_window_set_font(buddy, DefaultFont); - return tmp; -} - -/* - * Create a new radiobutton window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_radiobutton_new(char *text, ULONG id) -{ - HWND tmp = CreateWindow(BUTTONCLASSNAME, - text, - WS_CHILD | BS_AUTORADIOBUTTON | - WS_CLIPCHILDREN | WS_VISIBLE, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - BubbleButton *bubble = calloc(1, sizeof(BubbleButton)); - bubble->id = id; - bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); - bubble->cinfo.fore = -1; - bubble->cinfo.back = -1; - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - - -/* - * Create a new slider window (widget) to be packed. - * Parameters: - * vertical: TRUE or FALSE if slider is vertical. - * increments: Number of increments available. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_slider_new(int vertical, int increments, ULONG id) -{ - HWND tmp = CreateWindow(TRACKBAR_CLASS, - "", - WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | - (vertical ? TBS_VERT : TBS_HORZ), - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); - - cinfo->back = cinfo->fore = -1; - - cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc); - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - SendMessage(tmp, TBM_SETRANGE, (WPARAM)FALSE, (LPARAM)MAKELONG(0, increments-1)); - return tmp; -} - -/* - * Create a new scrollbar window (widget) to be packed. - * Parameters: - * vertical: TRUE or FALSE if scrollbar is vertical. - * increments: Number of increments available. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_scrollbar_new(int vertical, int increments, ULONG id) -{ - HWND tmp = CreateWindow(SCROLLBARCLASSNAME, - "", - WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | - (vertical ? SBS_VERT : SBS_HORZ), - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); - - cinfo->back = cinfo->fore = -1; - - cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc); - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - dw_window_set_data(tmp, "_dw_scrollbar", (void *)1); - return tmp; -} - -/* - * Create a new percent bar window (widget) to be packed. - * Parameters: - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_percent_new(ULONG id) -{ - return CreateWindow(PROGRESS_CLASS, - "", - WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); -} - -/* - * Create a new checkbox window (widget) to be packed. - * Parameters: - * text: The text to be display by the static text widget. - * id: An ID to be used with dw_window_from_id() or 0L. - */ -HWND API dw_checkbox_new(char *text, ULONG id) -{ - BubbleButton *bubble = calloc(1, sizeof(BubbleButton)); - HWND tmp = CreateWindow(BUTTONCLASSNAME, - text, - WS_CHILD | BS_AUTOCHECKBOX | - BS_TEXT | WS_CLIPCHILDREN | WS_VISIBLE, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - bubble->id = id; - bubble->checkbox = 1; - bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); - bubble->cinfo.fore = -1; - bubble->cinfo.back = -1; - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Create a new listbox window (widget) to be packed. - * Parameters: - * id: An ID to be used with dw_window_from_id() or 0L. - * multi: Multiple select TRUE or FALSE. - */ -HWND API dw_listbox_new(ULONG id, int multi) -{ - HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, - LISTBOXCLASSNAME, - "", - WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - WS_CHILD | LBS_HASSTRINGS | - LBS_NOTIFY | WS_BORDER | WS_CLIPCHILDREN | - WS_VSCROLL | (multi ? LBS_MULTIPLESEL : 0) , - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); - - if(!cinfo) - { - DestroyWindow(tmp); - return NULL; - } - - cinfo->cinfo.fore = -1; - cinfo->cinfo.back = -1; - cinfo->pOldProc = (WNDPROC)SubclassWindow(tmp, _containerwndproc); - - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); - dw_window_set_font(tmp, DefaultFont); - return tmp; -} - -/* - * Sets the icon used for a given window. - * Parameters: - * handle: Handle to the window. - * id: An ID to be used to specify the icon. - */ -void API dw_window_set_icon(HWND handle, ULONG id) -{ - HICON hicon = id < 65536 ? LoadIcon(DWInstance, MAKEINTRESOURCE(id)) : (HICON)id; - - SendMessage(handle, WM_SETICON, - (WPARAM) IMAGE_ICON, - (LPARAM) hicon); -} - -/* - * Sets the bitmap used for a given static window. - * Parameters: - * handle: Handle to the window. - * id: An ID to be used to specify the icon, - * (pass 0 if you use the filename param) - * filename: a path to a file (Bitmap on OS/2 or - * Windows and a pixmap on Unix, pass - * NULL if you use the id param) - */ -void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename) -{ - HBITMAP hbitmap; - HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, STM_GETIMAGE, IMAGE_BITMAP, 0); - - if(id) - hbitmap = LoadBitmap(DWInstance, MAKEINTRESOURCE(id)); - else if(filename) - { - char *file = malloc(strlen(filename) + 5); - - if (!file) - return; - - strcpy(file, filename); - - /* check if we can read from this file (it exists and read permission) */ - if(access(file, 04) != 0) - { - /* Try with .bmp extention */ - strcat(file, ".bmp"); - if(access(file, 04) != 0) - { - free(file); - return; - } - } - - hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); - free(file); - } - else - return; - - SendMessage(handle, STM_SETIMAGE, - (WPARAM) IMAGE_BITMAP, - (LPARAM) hbitmap); - - if(oldbitmap) - DeleteObject(oldbitmap); -} - -/* - * Sets the text used for a given window. - * Parameters: - * handle: Handle to the window. - * text: The text associsated with a given window. - */ -void API dw_window_set_text(HWND handle, char *text) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - SetWindowText(handle, text); - - /* Combobox */ - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - SendMessage(handle, CB_SETEDITSEL, 0, MAKELPARAM(-1, 0)); -} - -/* - * Gets the text used for a given window. - * Parameters: - * handle: Handle to the window. - * Returns: - * text: The text associsated with a given window. - */ -char * API dw_window_get_text(HWND handle) -{ - int len = GetWindowTextLength(handle); - char *tempbuf = calloc(1, len + 2); - - GetWindowText(handle, tempbuf, len + 1); - - return tempbuf; -} - -/* - * Disables given window (widget). - * Parameters: - * handle: Handle to the window. - */ -void API dw_window_disable(HWND handle) -{ - EnableWindow(handle, FALSE); -} - -/* - * Enables given window (widget). - * Parameters: - * handle: Handle to the window. - */ -void API dw_window_enable(HWND handle) -{ - EnableWindow(handle, TRUE); -} - -static HWND _dw_wfid_hwnd = NULL; - -BOOL CALLBACK _wfid(HWND handle, LPARAM lParam) -{ - if(GetWindowLong(handle, GWL_ID) == lParam) - { - _dw_wfid_hwnd = handle; - return FALSE; - } - return TRUE; -} - -/* - * Gets the child window handle with specified ID. - * Parameters: - * handle: Handle to the parent window. - * id: Integer ID of the child. - */ -HWND API dw_window_from_id(HWND handle, int id) -{ - _dw_wfid_hwnd = NULL; - EnumChildWindows(handle, _wfid, (LPARAM)id); - return _dw_wfid_hwnd; -} - -/* - * Pack windows (widgets) into a box from the start (or top). - * Parameters: - * box: Window handle of the box to be packed into. - * item: Window handle of the item to be back. - * width: Width in pixels of the item or -1 to be self determined. - * height: Height in pixels of the item or -1 to be self determined. - * hsize: TRUE if the window (widget) should expand horizontally to fill space given. - * vsize: TRUE if the window (widget) should expand vertically to fill space given. - * pad: Number of pixels of padding around the item. - */ -void API dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) -{ - Box *thisbox; - - /* - * If you try and pack an item into itself VERY bad things can happen; like at least an - * infinite loop on GTK! Lets be safe! - */ - if(box == item) - { - dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!",box,item); - return; - } - - thisbox = (Box *)GetWindowLongPtr(box, GWLP_USERDATA); - if(thisbox) - { - int z; - Item *tmpitem, *thisitem = thisbox->items; - char tmpbuf[100]; - - tmpitem = malloc(sizeof(Item)*(thisbox->count+1)); - - for(z=0;z<thisbox->count;z++) - { - tmpitem[z] = thisitem[z]; - } - - GetClassName(item, tmpbuf, 99); - - if(vsize && !height) - height = 1; - if(hsize && !width) - width = 1; - - if(strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1)==0) - tmpitem[thisbox->count].type = TYPEBOX; - else - { - if ( width == 0 && hsize == FALSE ) - dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item); - if ( height == 0 && vsize == FALSE ) - dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item); - - tmpitem[thisbox->count].type = TYPEITEM; - } - - tmpitem[thisbox->count].hwnd = item; - tmpitem[thisbox->count].origwidth = tmpitem[thisbox->count].width = width; - tmpitem[thisbox->count].origheight = tmpitem[thisbox->count].height = height; - tmpitem[thisbox->count].pad = pad; - if(hsize) - tmpitem[thisbox->count].hsize = SIZEEXPAND; - else - tmpitem[thisbox->count].hsize = SIZESTATIC; - - if(vsize) - tmpitem[thisbox->count].vsize = SIZEEXPAND; - else - tmpitem[thisbox->count].vsize = SIZESTATIC; - - thisbox->items = tmpitem; - - if(thisbox->count) - free(thisitem); - - thisbox->count++; - - SetParent(item, box); - if(strncmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0) - { - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(item, GWLP_USERDATA); - - if(cinfo) - { - SetParent(cinfo->buddy, box); - ShowWindow(cinfo->buddy, SW_SHOW); - SendMessage(item, UDM_SETBUDDY, (WPARAM)cinfo->buddy, 0); - } - } - } -} - -/* - * Sets the size of a given window (widget). - * Parameters: - * handle: Window (widget) handle. - * width: New width in pixels. - * height: New height in pixels. - */ -void API dw_window_set_usize(HWND handle, ULONG width, ULONG height) -{ - SetWindowPos(handle, (HWND)NULL, 0, 0, width, height, SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOMOVE); -} - -/* - * Returns the width of the screen. - */ -int API dw_screen_width(void) -{ - return GetSystemMetrics(SM_CXSCREEN); -} - -/* - * Returns the height of the screen. - */ -int API dw_screen_height(void) -{ - return GetSystemMetrics(SM_CYSCREEN); -} - -/* This should return the current color depth */ -unsigned long API dw_color_depth(void) -{ - int bpp; - HDC hdc = GetDC(HWND_DESKTOP); - - bpp = GetDeviceCaps(hdc, BITSPIXEL); - - ReleaseDC(HWND_DESKTOP, hdc); - - return bpp; -} - - -/* - * Sets the position of a given window (widget). - * Parameters: - * handle: Window (widget) handle. - * x: X location from the bottom left. - * y: Y location from the bottom left. - */ -void API dw_window_set_pos(HWND handle, ULONG x, ULONG y) -{ - SetWindowPos(handle, (HWND)NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); -} - -/* - * Sets the position and size of a given window (widget). - * Parameters: - * handle: Window (widget) handle. - * x: X location from the bottom left. - * y: Y location from the bottom left. - * width: Width of the widget. - * height: Height of the widget. - */ -void API dw_window_set_pos_size(HWND handle, ULONG x, ULONG y, ULONG width, ULONG height) -{ - SetWindowPos(handle, (HWND)NULL, x, y, width, height, SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE); -} - -/* - * Gets the position and size of a given window (widget). - * Parameters: - * handle: Window (widget) handle. - * x: X location from the bottom left. - * y: Y location from the bottom left. - * width: Width of the widget. - * height: Height of the widget. - */ -void API dw_window_get_pos_size(HWND handle, ULONG *x, ULONG *y, ULONG *width, ULONG *height) -{ - WINDOWPLACEMENT wp; - - wp.length = sizeof(WINDOWPLACEMENT); - - GetWindowPlacement(handle, &wp); - if( wp.showCmd == SW_SHOWMAXIMIZED) - { - if(x) - *x=0; - if(y) - *y=0; - if(width) - *width=dw_screen_width(); - if(height) - *height=dw_screen_height(); - } -else - { - if(x) - *x = wp.rcNormalPosition.left; - if(y) - *y = wp.rcNormalPosition.top; - if(width) - *width = wp.rcNormalPosition.right - wp.rcNormalPosition.left; - if(height) - *height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; - } -} - -/* - * Sets the style of a given window (widget). - * Parameters: - * handle: Window (widget) handle. - * width: New width in pixels. - * height: New height in pixels. - */ -void API dw_window_set_style(HWND handle, ULONG style, ULONG mask) -{ - ULONG tmp, currentstyle = GetWindowLong(handle, GWL_STYLE); - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - - tmp = currentstyle | mask; - tmp ^= mask; - tmp |= style; - - - /* We are using SS_NOPREFIX as a VCENTER flag */ - if(tmp & SS_NOPREFIX) - { - - if(cinfo) - cinfo->vcenter = 1; - else - { - cinfo = calloc(1, sizeof(ColorInfo)); - cinfo->fore = cinfo->back = -1; - cinfo->vcenter = 1; - - cinfo->pOldProc = SubclassWindow(handle, _colorwndproc); - SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo); - } - } - else if(cinfo) - cinfo->vcenter = 0; - - SetWindowLong(handle, GWL_STYLE, tmp); -} - -/* Finds the physical ID from the reference ID */ -int _findnotebookid(NotebookPage **array, int pageid) -{ - int z; - - for(z=0;z<256;z++) - { - if(array[z] && array[z]->realid == pageid) - return z; - } - return -1; -} - -/* - * Adds a new page to specified notebook. - * Parameters: - * handle: Window (widget) handle. - * flags: Any additional page creation flags. - * front: If TRUE page is added at the beginning. - */ -unsigned long API dw_notebook_page_new(HWND handle, ULONG flags, int front) -{ - NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); - - if(array) - { - int z, refid = -1; - - for(z=0;z<256;z++) - { - if(_findnotebookid(array, z) == -1) - { - refid = z; - break; - } - } - - if(refid == -1) - return -1; - - for(z=0;z<256;z++) - { - if(!array[z]) - { - int oldpage = TabCtrl_GetCurSel(handle); - - array[z] = calloc(1, sizeof(NotebookPage)); - array[z]->realid = refid; - array[z]->item.mask = TCIF_TEXT; - array[z]->item.iImage = -1; - array[z]->item.pszText = ""; - TabCtrl_InsertItem(handle, z, &(array[z]->item)); - - if(oldpage > -1 && array[oldpage]) - SetParent(array[oldpage]->hwnd, DW_HWND_OBJECT); - - TabCtrl_SetCurSel(handle, z); - return refid; - } - } - } - return -1; -} - -/* - * Sets the text on the specified notebook tab. - * Parameters: - * handle: Notebook handle. - * pageid: Page ID of the tab to set. - * text: Pointer to the text to set. - */ -void API dw_notebook_page_set_text(HWND handle, ULONG pageidx, char *text) -{ - - NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); - int pageid; - - if(!array) - return; - - pageid = _findnotebookid(array, pageidx); - - if(pageid > -1 && array[pageid]) - { - array[pageid]->item.mask = TCIF_TEXT; - array[pageid]->item.pszText = text; - TabCtrl_SetItem(handle, pageid, &(array[pageid]->item)); - _resize_notebook_page(handle, pageid); - } -} - -/* - * Sets the text on the specified notebook tab status area. - * Parameters: - * handle: Notebook handle. - * pageid: Page ID of the tab to set. - * text: Pointer to the text to set. - */ -void API dw_notebook_page_set_status_text(HWND handle, ULONG pageid, char *text) -{ -} - -/* - * Packs the specified box into the notebook page. - * Parameters: - * handle: Handle to the notebook to be packed. - * pageid: Page ID in the notebook which is being packed. - * page: Box handle to be packed. - */ -void API dw_notebook_pack(HWND handle, ULONG pageidx, HWND page) -{ - NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); - int pageid; - - if(!array) - return; - - pageid = _findnotebookid(array, pageidx); - - if(pageid > -1 && array[pageid]) - { - HWND tmpbox = dw_box_new(DW_VERT, 0); - - dw_box_pack_start(tmpbox, page, 0, 0, TRUE, TRUE, 0); - SubclassWindow(tmpbox, _wndproc); - if(array[pageid]->hwnd) - dw_window_destroy(array[pageid]->hwnd); - array[pageid]->hwnd = tmpbox; - if(pageidx == dw_notebook_page_query(handle)) - { - SetParent(tmpbox, handle); - _resize_notebook_page(handle, pageid); - } - } -} - -/* - * Remove a page from a notebook. - * Parameters: - * handle: Handle to the notebook widget. - * pageid: ID of the page to be destroyed. - */ -void API dw_notebook_page_destroy(HWND handle, unsigned int pageidx) -{ - NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); - int newid = -1, z, pageid; - - if(!array) - return; - - pageid = _findnotebookid(array, pageidx); - - if(pageid < 0) - return; - - if(array[pageid]) - { - SetParent(array[pageid]->hwnd, DW_HWND_OBJECT); - free(array[pageid]); - array[pageid] = NULL; - } - - TabCtrl_DeleteItem(handle, pageid); - - /* Shift the pages over 1 */ - for(z=pageid;z<255;z++) - array[z] = array[z+1]; - array[255] = NULL; - - for(z=0;z<256;z++) - { - if(array[z]) - { - newid = z; - break; - } - } - if(newid > -1) - { - SetParent(array[newid]->hwnd, handle); - _resize_notebook_page(handle, newid); - dw_notebook_page_set(handle, array[newid]->realid); - } -} - -/* - * Queries the currently visible page ID. - * Parameters: - * handle: Handle to the notebook widget. - */ -unsigned long API dw_notebook_page_query(HWND handle) -{ - NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); - int physid = TabCtrl_GetCurSel(handle); - - if(physid > -1 && physid < 256 && array && array[physid]) - return array[physid]->realid; - return -1; -} - -/* - * Sets the currently visible page ID. - * Parameters: - * handle: Handle to the notebook widget. - * pageid: ID of the page to be made visible. - */ -void API dw_notebook_page_set(HWND handle, unsigned int pageidx) -{ - NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); - int pageid; - - if(!array) - return; - - pageid = _findnotebookid(array, pageidx); - - if(pageid > -1 && pageid < 256) - { - int oldpage = TabCtrl_GetCurSel(handle); - - if(oldpage > -1 && array && array[oldpage]) - SetParent(array[oldpage]->hwnd, DW_HWND_OBJECT); - - TabCtrl_SetCurSel(handle, pageid); - - SetParent(array[pageid]->hwnd, handle); - _resize_notebook_page(handle, pageid); - } -} - -/* - * Appends the specified text to the listbox's (or combobox) entry list. - * Parameters: - * handle: Handle to the listbox to be appended to. - * text: Text to append into listbox. - */ -void API dw_listbox_append(HWND handle, char *text) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - SendMessage(handle, - CB_ADDSTRING, - 0, (LPARAM)text); - else - SendMessage(handle, - LB_ADDSTRING, - 0, (LPARAM)text); -} - -/* - * Clears the listbox's (or combobox) list of all entries. - * Parameters: - * handle: Handle to the listbox to be cleared. - */ -void API dw_listbox_clear(HWND handle) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - { - char *buf = dw_window_get_text(handle); - - SendMessage(handle, - CB_RESETCONTENT, 0L, 0L); - - if(buf) - { - dw_window_set_text(handle, buf); - free(buf); - } - } - else - SendMessage(handle, - LB_RESETCONTENT, 0L, 0L); -} - -/* - * Sets the text of a given listbox entry. - * Parameters: - * handle: Handle to the listbox to be queried. - * index: Index into the list to be queried. - * buffer: Buffer where text will be copied. - */ -void API dw_listbox_set_text(HWND handle, unsigned int index, char *buffer) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - { - SendMessage(handle, CB_DELETESTRING, (WPARAM)index, 0); - SendMessage(handle, CB_INSERTSTRING, (WPARAM)index, (LPARAM)buffer); - } - else - { - unsigned int sel = (unsigned int)SendMessage(handle, LB_GETCURSEL, 0, 0); - SendMessage(handle, LB_DELETESTRING, (WPARAM)index, 0); - SendMessage(handle, LB_INSERTSTRING, (WPARAM)index, (LPARAM)buffer); - SendMessage(handle, LB_SETCURSEL, (WPARAM)sel, 0); - SendMessage(handle, LB_SETSEL, (WPARAM)TRUE, (LPARAM)sel); - } -} - -/* - * Copies the given index item's text into buffer. - * Parameters: - * handle: Handle to the listbox to be queried. - * index: Index into the list to be queried. - * buffer: Buffer where text will be copied. - * length: Length of the buffer (including NULL). - */ -void API dw_listbox_query_text(HWND handle, unsigned int index, char *buffer, unsigned int length) -{ - char tmpbuf[100]; - int len; - - if(!buffer || !length) - return; - - buffer[0] = 0; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - { - len = (int)SendMessage(handle, CB_GETLBTEXTLEN, (WPARAM)index, 0); - - if(len < length && len != CB_ERR) - SendMessage(handle, - CB_GETLBTEXT, (WPARAM)index, (LPARAM)buffer); - } - else - { - len = (int)SendMessage(handle, LB_GETTEXTLEN, (WPARAM)index, 0); - - if(len < length && len != LB_ERR) - SendMessage(handle, - LB_GETTEXT, (WPARAM)index, (LPARAM)buffer); - } -} - -/* - * Returns the index to the item in the list currently selected. - * Parameters: - * handle: Handle to the listbox to be queried. - */ -unsigned int API dw_listbox_selected(HWND handle) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - return (unsigned int)SendMessage(handle, - CB_GETCURSEL, - 0, 0); - - return (unsigned int)SendMessage(handle, - LB_GETCURSEL, - 0, 0); -} - -/* - * Returns the index to the current selected item or -1 when done. - * Parameters: - * handle: Handle to the listbox to be queried. - * where: Either the previous return or -1 to restart. - */ -int API dw_listbox_selected_multi(HWND handle, int where) -{ - int *array, count, z; - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - /* This doesn't work on comboboxes */ - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - return -1; - - count = (int)SendMessage(handle, LB_GETSELCOUNT, 0, 0); - if(count > 0) - { - array = malloc(sizeof(int)*count); - SendMessage(handle, LB_GETSELITEMS, (WPARAM)count, (LPARAM)array); - - if(where == -1) - { - int ret = array[0]; - free(array); - return ret; - } - for(z=0;z<count;z++) - { - if(array[z] == where && (z+1) < count) - { - int ret = array[z+1]; - free(array); - return ret; - } - } - free(array); - } - return -1; -} - -/* - * Sets the selection state of a given index. - * Parameters: - * handle: Handle to the listbox to be set. - * index: Item index. - * state: TRUE if selected FALSE if unselected. - */ -void API dw_listbox_select(HWND handle, int index, int state) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - SendMessage(handle, CB_SETCURSEL, (WPARAM)index, 0); - else - { - SendMessage(handle, LB_SETCURSEL, (WPARAM)index, 0); - SendMessage(handle, LB_SETSEL, (WPARAM)state, (LPARAM)index); - } - _wndproc(handle, WM_COMMAND, (WPARAM)(LBN_SELCHANGE << 16), (LPARAM)handle); -} - -/* - * Deletes the item with given index from the list. - * Parameters: - * handle: Handle to the listbox to be set. - * index: Item index. - */ -void API dw_listbox_delete(HWND handle, int index) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - SendMessage(handle, CB_DELETESTRING, (WPARAM)index, 0); - else - SendMessage(handle, LB_DELETESTRING, (WPARAM)index, 0); -} - -/* - * Returns the listbox's item count. - * Parameters: - * handle: Handle to the listbox to be cleared. - */ -int API dw_listbox_count(HWND handle) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - return (int)SendMessage(handle, - CB_GETCOUNT,0L, 0L); - - return (int)SendMessage(handle, - LB_GETCOUNT,0L, 0L); -} - -/* - * Sets the topmost item in the viewport. - * Parameters: - * handle: Handle to the listbox to be cleared. - * top: Index to the top item. - */ -void API dw_listbox_set_top(HWND handle, int top) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - /* This doesn't work on comboboxes */ - if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) - return; - - SendMessage(handle, LB_SETTOPINDEX, (WPARAM)top, 0); -} - -/* - * Adds text to an MLE box and returns the current point. - * Parameters: - * handle: Handle to the MLE to be queried. - * buffer: Text buffer to be imported. - * startpoint: Point to start entering text. - */ -unsigned int API dw_mle_import(HWND handle, char *buffer, int startpoint) -{ - int textlen, len = GetWindowTextLength(handle); - char *tmpbuf; - - if((textlen = strlen(buffer)) < 1) - return startpoint; - - startpoint++; - tmpbuf = calloc(1, len + textlen + startpoint + 2); - - if(startpoint < 0) - startpoint = 0; - - if(len) - { - char *dest, *start; - int copylen = len - startpoint; - - GetWindowText(handle, tmpbuf, len+1); - - dest = &tmpbuf[startpoint+textlen-1]; - start = &tmpbuf[startpoint]; - - if(copylen > 0) - memcpy(dest, start, copylen); - } - memcpy(&tmpbuf[startpoint], buffer, textlen); - - SetWindowText(handle, tmpbuf); - - free(tmpbuf); - return (startpoint + textlen - 1); -} - -/* - * Grabs text from an MLE box. - * Parameters: - * handle: Handle to the MLE to be queried. - * buffer: Text buffer to be exported. - * startpoint: Point to start grabbing text. - * length: Amount of text to be grabbed. - */ -void API dw_mle_export(HWND handle, char *buffer, int startpoint, int length) -{ - int max, len = GetWindowTextLength(handle); - char *tmpbuf = calloc(1, len+2); - - if(len) - GetWindowText(handle, tmpbuf, len+1); - - buffer[0] = 0; - - if(startpoint < len) - { - max = MIN(length, len - startpoint); - - memcpy(buffer, &tmpbuf[startpoint], max); - } - - free(tmpbuf); -} - -/* - * Obtains information about an MLE box. - * Parameters: - * handle: Handle to the MLE to be queried. - * bytes: A pointer to a variable to return the total bytes. - * lines: A pointer to a variable to return the number of lines. - */ -void API dw_mle_query(HWND handle, unsigned long *bytes, unsigned long *lines) -{ - if(bytes) - *bytes = GetWindowTextLength(handle); - if(lines) - *lines = (unsigned long)SendMessage(handle, EM_GETLINECOUNT, 0, 0); -} - -/* - * Deletes text from an MLE box. - * Parameters: - * handle: Handle to the MLE to be deleted from. - * startpoint: Point to start deleting text. - * length: Amount of text to be deleted. - */ -void API dw_mle_delete(HWND handle, int startpoint, int length) -{ - int len = GetWindowTextLength(handle); - char *tmpbuf = calloc(1, len+2); - - GetWindowText(handle, tmpbuf, len+1); - - if(startpoint + length < len) - { - strcpy(&tmpbuf[startpoint], &tmpbuf[startpoint+length]); - - SetWindowText(handle, tmpbuf); - } - - free(tmpbuf); -} - -/* - * Clears all text from an MLE box. - * Parameters: - * handle: Handle to the MLE to be cleared. - */ -void API dw_mle_clear(HWND handle) -{ - SetWindowText(handle, ""); -} - -/* - * Sets the visible line of an MLE box. - * Parameters: - * handle: Handle to the MLE. - * line: Line to be visible. - */ -void API dw_mle_set_visible(HWND handle, int line) -{ - int point = (int)SendMessage(handle, EM_LINEINDEX, (WPARAM)line, 0); - dw_mle_set(handle, point); -} - -/* - * Sets the editablity of an MLE box. - * Parameters: - * handle: Handle to the MLE. - * state: TRUE if it can be edited, FALSE for readonly. - */ -void API dw_mle_set_editable(HWND handle, int state) -{ - SendMessage(handle, EM_SETREADONLY, (WPARAM)(state ? FALSE : TRUE), 0); -} - -/* - * Sets the word wrap state of an MLE box. - * Parameters: - * handle: Handle to the MLE. - * state: TRUE if it wraps, FALSE if it doesn't. - */ -void API dw_mle_set_word_wrap(HWND handle, int state) -{ - /* If ES_AUTOHSCROLL is not set and there is not - * horizontal scrollbar it word wraps. - */ - if(state) - dw_window_set_style(handle, 0, ES_AUTOHSCROLL); - else - dw_window_set_style(handle, ES_AUTOHSCROLL, ES_AUTOHSCROLL); -} - -/* - * Sets the current cursor position of an MLE box. - * Parameters: - * handle: Handle to the MLE to be positioned. - * point: Point to position cursor. - */ -void API dw_mle_set(HWND handle, int point) -{ - SendMessage(handle, EM_SETSEL, 0, MAKELONG(point,point)); - SendMessage(handle, EM_SCROLLCARET, 0, 0); -} - -/* - * Finds text in an MLE box. - * Parameters: - * handle: Handle to the MLE to be cleared. - * text: Text to search for. - * point: Start point of search. - * flags: Search specific flags. - */ -int API dw_mle_search(HWND handle, char *text, int point, unsigned long flags) -{ - int len = GetWindowTextLength(handle); - char *tmpbuf = calloc(1, len+2); - int z, textlen, retval = 0; - - GetWindowText(handle, tmpbuf, len+1); - - textlen = strlen(text); - - if(flags & DW_MLE_CASESENSITIVE) - { - for(z=point;z<(len-textlen) && !retval;z++) - { - if(strncmp(&tmpbuf[z], text, textlen) == 0) - retval = z + textlen; - } - } - else - { - for(z=point;z<(len-textlen) && !retval;z++) - { - if(strnicmp(&tmpbuf[z], text, textlen) == 0) - retval = z + textlen; - } - } - - if(retval) - { - SendMessage(handle, EM_SETSEL, (WPARAM)retval - textlen, (LPARAM)retval); - SendMessage(handle, EM_SCROLLCARET, 0, 0); - } - - free(tmpbuf); - - return retval; -} - -/* - * Stops redrawing of an MLE box. - * Parameters: - * handle: Handle to the MLE to freeze. - */ -void API dw_mle_freeze(HWND handle) -{ -} - -/* - * Resumes redrawing of an MLE box. - * Parameters: - * handle: Handle to the MLE to thaw. - */ -void API dw_mle_thaw(HWND handle) -{ -} - -/* - * Returns the range of the percent bar. - * Parameters: - * handle: Handle to the percent bar to be queried. - */ -unsigned int API dw_percent_query_range(HWND handle) -{ - return (unsigned int)SendMessage(handle, PBM_GETRANGE, (WPARAM)FALSE, 0); -} - -/* - * Sets the percent bar position. - * Parameters: - * handle: Handle to the percent bar to be set. - * position: Position of the percent bar withing the range. - */ -void API dw_percent_set_pos(HWND handle, unsigned int position) -{ - SendMessage(handle, PBM_SETPOS, (WPARAM)position, 0); -} - -/* - * Returns the position of the slider. - * Parameters: - * handle: Handle to the slider to be queried. - */ -unsigned int API dw_slider_query_pos(HWND handle) -{ - int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0); - ULONG currentstyle = GetWindowLong(handle, GWL_STYLE); - - if(currentstyle & TBS_VERT) - return max - (unsigned int)SendMessage(handle, TBM_GETPOS, 0, 0); - return (unsigned int)SendMessage(handle, TBM_GETPOS, 0, 0); -} - -/* - * Sets the slider position. - * Parameters: - * handle: Handle to the slider to be set. - * position: Position of the slider withing the range. - */ -void API dw_slider_set_pos(HWND handle, unsigned int position) -{ - int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0); - ULONG currentstyle = GetWindowLong(handle, GWL_STYLE); - - if(currentstyle & TBS_VERT) - SendMessage(handle, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)max - position); - else - SendMessage(handle, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)position); -} - -/* - * Returns the position of the scrollbar. - * Parameters: - * handle: Handle to the scrollbar to be queried. - */ -unsigned int API dw_scrollbar_query_pos(HWND handle) -{ - return (unsigned int)SendMessage(handle, SBM_GETPOS, 0, 0); -} - -/* - * Sets the scrollbar position. - * Parameters: - * handle: Handle to the scrollbar to be set. - * position: Position of the scrollbar withing the range. - */ -void API dw_scrollbar_set_pos(HWND handle, unsigned int position) -{ - dw_window_set_data(handle, "_dw_scrollbar_value", (void *)position); - SendMessage(handle, SBM_SETPOS, (WPARAM)position, (LPARAM)TRUE); -} - -/* - * Sets the scrollbar range. - * Parameters: - * handle: Handle to the scrollbar to be set. - * range: Maximum range value. - * visible: Visible area relative to the range. - */ -void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible) -{ - SCROLLINFO si; - - si.cbSize = sizeof(SCROLLINFO); - si.fMask = SIF_RANGE | SIF_PAGE; - si.nMin = 0; - si.nMax = range - 1; - si.nPage = visible; - SendMessage(handle, SBM_SETSCROLLINFO, (WPARAM)TRUE, (LPARAM)&si); -} - -/* - * Sets the spinbutton value. - * Parameters: - * handle: Handle to the spinbutton to be set. - * position: Current value of the spinbutton. - */ -void API dw_spinbutton_set_pos(HWND handle, long position) -{ - char tmpbuf[100]; - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - - sprintf(tmpbuf, "%d", position); - - if(cinfo && cinfo->buddy) - SetWindowText(cinfo->buddy, tmpbuf); - - if(IS_IE5PLUS) - SendMessage(handle, UDM_SETPOS32, 0, (LPARAM)position); - else - SendMessage(handle, UDM_SETPOS, 0, (LPARAM)MAKELONG((short)position, 0)); -} - -/* - * Sets the spinbutton limits. - * Parameters: - * handle: Handle to the spinbutton to be set. - * position: Current value of the spinbutton. - * position: Current value of the spinbutton. - */ -void API dw_spinbutton_set_limits(HWND handle, long upper, long lower) -{ - if(IS_IE5PLUS) - SendMessage(handle, UDM_SETRANGE32, (WPARAM)lower,(LPARAM)upper); - else - SendMessage(handle, UDM_SETRANGE32, (WPARAM)((short)lower), - (LPARAM)((short)upper)); -} - -/* - * Sets the entryfield character limit. - * Parameters: - * handle: Handle to the spinbutton to be set. - * limit: Number of characters the entryfield will take. - */ -void API dw_entryfield_set_limit(HWND handle, ULONG limit) -{ - SendMessage(handle, EM_SETLIMITTEXT, (WPARAM)limit, 0); -} - -/* - * Returns the current value of the spinbutton. - * Parameters: - * handle: Handle to the spinbutton to be queried. - */ -long API dw_spinbutton_query(HWND handle) -{ - if(IS_IE5PLUS) - return (long)SendMessage(handle, UDM_GETPOS32, 0, 0); - else - return (long)SendMessage(handle, UDM_GETPOS, 0, 0); -} - -/* - * Returns the state of the checkbox. - * Parameters: - * handle: Handle to the checkbox to be queried. - */ -int API dw_checkbox_query(HWND handle) -{ - if(SendMessage(handle, BM_GETCHECK, 0, 0) == BST_CHECKED) - return (in_checkbox_handler ? FALSE : TRUE); - return (in_checkbox_handler ? TRUE : FALSE); -} - -/* This function unchecks all radiobuttons on a box */ -BOOL CALLBACK _uncheck_radios(HWND handle, LPARAM lParam) -{ - char tmpbuf[100]; - - GetClassName(handle, tmpbuf, 99); - - if(strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0) - { - BubbleButton *bubble= (BubbleButton *)GetWindowLongPtr(handle, GWLP_USERDATA); - - if(bubble && !bubble->checkbox) - SendMessage(handle, BM_SETCHECK, 0, 0); - } - return TRUE; -} -/* - * Sets the state of the checkbox. - * Parameters: - * handle: Handle to the checkbox to be queried. - * value: TRUE for checked, FALSE for unchecked. - */ -void API dw_checkbox_set(HWND handle, int value) -{ - BubbleButton *bubble= (BubbleButton *)GetWindowLongPtr(handle, GWLP_USERDATA); - - if(bubble && !bubble->checkbox) - { - HWND parent = GetParent(handle); - - if(parent) - EnumChildWindows(parent, _uncheck_radios, 0); - } - SendMessage(handle, BM_SETCHECK, (WPARAM)value, 0); -} - -/* - * Inserts an item into a tree window (widget) after another item. - * Parameters: - * handle: Handle to the tree to be inserted. - * item: Handle to the item to be positioned after. - * title: The text title of the entry. - * icon: Handle to coresponding icon. - * parent: Parent handle or 0 if root. - * itemdata: Item specific data. - */ -HTREEITEM API dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, unsigned long icon, HTREEITEM parent, void *itemdata) -{ - 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 = title; - tvi.lParam = (LONG)ptrs; - tvi.cchTextMax = strlen(title); - tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1); - - tvins.item = tvi; - tvins.hParent = parent; - tvins.hInsertAfter = item ? item : TVI_FIRST; - - hti = TreeView_InsertItem(handle, &tvins); - - return hti; -} - -/* - * Inserts an item into a tree window (widget). - * Parameters: - * handle: Handle to the tree to be inserted. - * title: The text title of the entry. - * icon: Handle to coresponding icon. - * parent: Parent handle or 0 if root. - * itemdata: Item specific data. - */ -HTREEITEM API dw_tree_insert(HWND handle, char *title, unsigned long icon, HTREEITEM parent, void *itemdata) -{ - 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 = title; - tvi.lParam = (LONG)ptrs; - tvi.cchTextMax = strlen(title); - tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1); - - tvins.item = tvi; - tvins.hParent = parent; - tvins.hInsertAfter = TVI_LAST; - - hti = TreeView_InsertItem(handle, &tvins); - - return hti; -} - -/* - * Sets the text and icon of an item in a tree window (widget). - * Parameters: - * handle: Handle to the tree containing the item. - * item: Handle of the item to be modified. - * title: The text title of the entry. - * icon: Handle to coresponding icon. - */ -void API dw_tree_set(HWND handle, HTREEITEM item, char *title, unsigned long 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 = title; - tvi.cchTextMax = strlen(title); - tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1); - tvi.hItem = (HTREEITEM)item; - - TreeView_SetItem(handle, &tvi); - } -} - -/* - * Sets the item data of a tree item. - * Parameters: - * handle: Handle to the tree containing the item. - * item: Handle of the item to be modified. - * itemdata: User defined data to be associated with item. - */ -void API dw_tree_set_data(HWND handle, HTREEITEM item, void *itemdata) -{ - TVITEM tvi; - void **ptrs; - - tvi.mask = TVIF_HANDLE; - tvi.hItem = item; - - if(TreeView_GetItem(handle, &tvi)) - { - ptrs = (void **)tvi.lParam; - ptrs[1] = itemdata; - } -} - -/* - * Gets the item data of a tree item. - * Parameters: - * handle: Handle to the tree containing the item. - * item: Handle of the item to be modified. - */ -void * API dw_tree_get_data(HWND handle, HTREEITEM item) -{ - TVITEM tvi; - void **ptrs; - - tvi.mask = TVIF_HANDLE; - tvi.hItem = item; - - if(TreeView_GetItem(handle, &tvi)) - { - ptrs = (void **)tvi.lParam; - return ptrs[1]; - } - return NULL; -} - -/* - * Gets the text an item in a tree window (widget). - * Parameters: - * handle: Handle to the tree containing the item. - * item: Handle of the item to be modified. - */ -char * API dw_tree_get_title(HWND handle, HTREEITEM item) -{ - TVITEM tvi; - - tvi.mask = TVIF_HANDLE; - tvi.hItem = item; - - if(TreeView_GetItem(handle, &tvi)) - return tvi.pszText; - return NULL; -} - -/* - * Gets the text an item in a tree window (widget). - * Parameters: - * handle: Handle to the tree containing the item. - * item: Handle of the item to be modified. - */ -HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item) -{ - return TreeView_GetParent(handle, item); -} - -/* - * Sets this item as the active selection. - * Parameters: - * handle: Handle to the tree window (widget) to be selected. - * item: Handle to the item to be selected. - */ -void API dw_tree_item_select(HWND handle, HTREEITEM item) -{ - dw_window_set_data(handle, "_dw_select_item", (void *)1); - TreeView_SelectItem(handle, item); - dw_window_set_data(handle, "_dw_select_item", (void *)0); -} - -/* Delete all tree subitems */ -void _dw_tree_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_delete(handle, lastitem); - } -} - -/* - * Removes all nodes from a tree. - * Parameters: - * handle: Handle to the window (widget) to be cleared. - */ -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_delete_recursive(handle, hti); - hti = TreeView_GetNextSibling(handle, hti); - dw_tree_delete(handle, lastitem); - } - dw_window_set_data(handle, "_dw_select_item", (void *)0); -} - -/* - * Expands a node on a tree. - * Parameters: - * handle: Handle to the tree window (widget). - * item: Handle to node to be expanded. - */ -void API dw_tree_expand(HWND handle, HTREEITEM item) -{ - TreeView_Expand(handle, item, TVE_EXPAND); -} - -/* - * Collapses a node on a tree. - * Parameters: - * handle: Handle to the tree window (widget). - * item: Handle to node to be collapsed. - */ -void API dw_tree_collapse(HWND handle, HTREEITEM item) -{ - TreeView_Expand(handle, item, TVE_COLLAPSE); -} - -/* - * Removes a node from a tree. - * Parameters: - * handle: Handle to the window (widget) to be cleared. - * item: Handle to node to be deleted. - */ -void API dw_tree_delete(HWND handle, HTREEITEM item) -{ - TVITEM tvi; - void **ptrs; - - if(item == TVI_ROOT || !item) - return; - - tvi.mask = TVIF_HANDLE; - tvi.hItem = item; - - if(TreeView_GetItem(handle, &tvi)) - ptrs = (void **)tvi.lParam; - - _dw_tree_delete_recursive(handle, item); - TreeView_DeleteItem(handle, item); - if(ptrs) - free(ptrs); -} - -/* - * Sets up the container columns. - * Parameters: - * handle: Handle to the container to be configured. - * flags: An array of unsigned longs with column flags. - * titles: An array of strings with column text titles. - * count: The number of columns (this should match the arrays). - * separator: The column number that contains the main separator. - * (only used on OS/2 but must be >= 0 on all) - */ -int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator) -{ - ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - int z, l = 0; - unsigned long *tempflags = calloc(sizeof(unsigned long), count + 2); - LVCOLUMN lvc; - - if(separator == -1) - { - tempflags[0] = DW_CFA_RESERVED; - l = 1; - } - - memcpy(&tempflags[l], flags, sizeof(unsigned long) * count); - tempflags[count + l] = 0; - cinfo->flags = tempflags; - cinfo->columns = count + l; - - - for(z=0;z<count;z++) - { - if(titles[z]) - { - lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_FMT; - lvc.pszText = titles[z]; - lvc.cchTextMax = strlen(titles[z]); - if(flags[z] & DW_CFA_RIGHT) - lvc.fmt = LVCFMT_RIGHT; - else if(flags[z] & DW_CFA_CENTER) - lvc.fmt = LVCFMT_CENTER; - else - lvc.fmt = LVCFMT_LEFT; - lvc.cx = 75; - lvc.iSubItem = count; - SendMessage(handle, LVM_INSERTCOLUMN, (WPARAM)z + l, (LPARAM)&lvc); - } - } - ListView_SetExtendedListViewStyle(handle, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES); - return TRUE; -} - -/* - * Sets up the filesystem columns, note: filesystem always has an icon/filename field. - * Parameters: - * handle: Handle to the container to be configured. - * flags: An array of unsigned longs with column flags. - * titles: An array of strings with column text titles. - * count: The number of columns (this should match the arrays). - */ -int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count) -{ - LV_COLUMN lvc; - - lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; - lvc.pszText = "Filename"; - lvc.cchTextMax = 8; - lvc.fmt = 0; - if(!count) - lvc.cx = 300; - else - lvc.cx = 150; - lvc.iSubItem = count; - SendMessage(handle, LVM_INSERTCOLUMN, (WPARAM)0, (LPARAM)&lvc); - dw_container_setup(handle, flags, titles, count, -1); - return TRUE; -} - -/* - * Obtains an icon from a module (or header in GTK). - * Parameters: - * module: Handle to module (DLL) in OS/2 and Windows. - * id: A unsigned long id int the resources on OS/2 and - * Windows, on GTK this is converted to a pointer - * to an embedded XPM. - */ -unsigned long API dw_icon_load(unsigned long module, unsigned long id) -{ - return (unsigned long)LoadIcon(DWInstance, MAKEINTRESOURCE(id)); -} - -/* - * Obtains an icon from a file. - * Parameters: - * filename: Name of the file, omit extention to have - * DW pick the appropriate file extension. - * (ICO on OS/2 or Windows, XPM on Unix) - */ -unsigned long API dw_icon_load_from_file(char *filename) -{ - char *file = malloc(strlen(filename) + 5); - HANDLE icon; - - if(!file) - return 0; - - strcpy(file, filename); - - /* check if we can read from this file (it exists and read permission) */ - if(access(file, 04) != 0) - { - /* Try with .bmp extention */ - strcat(file, ".ico"); - if(access(file, 04) != 0) - { - free(file); - return 0; - } - } - icon = LoadImage(NULL, file, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); - free(file); - return (unsigned long)icon; -} - -/* - * Frees a loaded resource in OS/2 and Windows. - * Parameters: - * handle: Handle to icon returned by dw_icon_load(). - */ -void API dw_icon_free(unsigned long handle) -{ - DestroyIcon((HICON)handle); -} - -/* - * Allocates memory used to populate a container. - * Parameters: - * handle: Handle to the container window (widget). - * rowcount: The number of items to be populated. - */ -void * API dw_container_alloc(HWND handle, int rowcount) -{ - LV_ITEM lvi; - int z; - - lvi.mask = LVIF_DI_SETITEM | LVIF_TEXT | LVIF_IMAGE; - lvi.iSubItem = 0; - /* Insert at the end */ - lvi.iItem = 1000000; - lvi.pszText = ""; - lvi.cchTextMax = 1; - lvi.iImage = -1; - - ShowWindow(handle, SW_HIDE); - for(z=0;z<rowcount;z++) - ListView_InsertItem(handle, &lvi); - return (void *)handle; -} - -/* Finds a icon in the table, otherwise it adds it to the table - * and returns the index in the table. - */ -int _lookup_icon(HWND handle, HICON hicon, int type) -{ - int z; - static HWND lasthwnd = NULL; - - if(!hSmall || !hLarge) - { - hSmall = ImageList_Create(16, 16, ILC_COLOR16 | ILC_MASK, ICON_INDEX_LIMIT, 0); - hLarge = ImageList_Create(32, 32, ILC_COLOR16 | ILC_MASK, ICON_INDEX_LIMIT, 0); - } - for(z=0;z<ICON_INDEX_LIMIT;z++) - { - if(!lookup[z]) - { - lookup[z] = hicon; - ImageList_AddIcon(hSmall, hicon); - ImageList_AddIcon(hLarge, hicon); - if(type) - { - TreeView_SetImageList(handle, hSmall, TVSIL_NORMAL); - } - else - { - ListView_SetImageList(handle, hSmall, LVSIL_SMALL); - ListView_SetImageList(handle, hLarge, LVSIL_NORMAL); - } - lasthwnd = handle; - return z; - } - - if(hicon == lookup[z]) - { - if(lasthwnd != handle) - { - if(type) - { - TreeView_SetImageList(handle, hSmall, TVSIL_NORMAL); - } - else - { - ListView_SetImageList(handle, hSmall, LVSIL_SMALL); - ListView_SetImageList(handle, hLarge, LVSIL_NORMAL); - } - lasthwnd = handle; - } - return z; - } - } - return -1; -} - -/* - * Sets an item in specified row and column to the given data. - * Parameters: - * handle: Handle to the container window (widget). - * pointer: Pointer to the allocated memory in dw_container_alloc(). - * column: Zero based column of data being set. - * row: Zero based row of data being set. - * data: Pointer to the data to be added. - */ -void API dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, unsigned long icon) -{ - LV_ITEM lvi; - - lvi.iItem = row; - lvi.iSubItem = 0; - lvi.mask = LVIF_DI_SETITEM | LVIF_IMAGE | LVIF_TEXT; - lvi.pszText = filename; - lvi.cchTextMax = strlen(filename); - lvi.iImage = _lookup_icon(handle, (HICON)icon, 0); - - ListView_SetItem(handle, &lvi); -} - -/* - * Sets an item in specified row and column to the given data. - * Parameters: - * handle: Handle to the container window (widget). - * pointer: Pointer to the allocated memory in dw_container_alloc(). - * column: Zero based column of data being set. - * row: Zero based row of data being set. - * data: Pointer to the data to be added. - */ -void API dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data) -{ - dw_container_set_item(handle, pointer, column + 1, row, data); -} - -/* - * Sets an item in specified row and column to the given data. - * Parameters: - * handle: Handle to the container window (widget). - * pointer: Pointer to the allocated memory in dw_container_alloc(). - * column: Zero based column of data being set. - * row: Zero based row of data being set. - * data: Pointer to the data to be added. - */ -void API dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data) -{ - ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - ULONG *flags; - LV_ITEM lvi; - char textbuffer[100], *destptr = textbuffer; - - if(!cinfo || !cinfo->flags || !data) - return; - - flags = cinfo->flags; - - lvi.mask = LVIF_DI_SETITEM | LVIF_TEXT; - lvi.iItem = row; - lvi.iSubItem = column; - - if(flags[column] & DW_CFA_BITMAPORICON) - { - HICON hicon = *((HICON *)data); - - lvi.mask = LVIF_DI_SETITEM | LVIF_IMAGE; - lvi.pszText = NULL; - lvi.cchTextMax = 0; - - lvi.iImage = _lookup_icon(handle, hicon, 0); - } - else if(flags[column] & DW_CFA_STRING) - { - char *tmp = *((char **)data); - - if(!tmp) - tmp = ""; - - lvi.pszText = tmp; - lvi.cchTextMax = strlen(tmp); - destptr = tmp; - } - else if(flags[column] & DW_CFA_ULONG) - { - ULONG tmp = *((ULONG *)data); - - sprintf(textbuffer, "%lu", tmp); - - lvi.pszText = textbuffer; - lvi.cchTextMax = strlen(textbuffer); - } - else if(flags[column] & DW_CFA_DATE) - { - struct tm curtm; - CDATE cdate = *((CDATE *)data); - - curtm.tm_mday = cdate.day; - curtm.tm_mon = cdate.month - 1; - curtm.tm_year = cdate.year - 1900; - - strftime(textbuffer, 100, "%x", &curtm); - - lvi.pszText = textbuffer; - lvi.cchTextMax = strlen(textbuffer); - } - else if(flags[column] & DW_CFA_TIME) - { - struct tm curtm; - CTIME ctime = *((CTIME *)data); - - curtm.tm_hour = ctime.hours; - curtm.tm_min = ctime.minutes; - curtm.tm_sec = ctime.seconds; - - strftime(textbuffer, 100, "%X", &curtm); - - lvi.pszText = textbuffer; - lvi.cchTextMax = strlen(textbuffer); - } - - ListView_SetItem(handle, &lvi); -} - -/* - * Changes an existing item in specified row and column to the given data. - * Parameters: - * handle: Handle to the container window (widget). - * column: Zero based column of data being set. - * row: Zero based row of data being set. - * data: Pointer to the data to be added. - */ -void API dw_container_change_item(HWND handle, int column, int row, void *data) -{ - dw_container_set_item(handle, NULL, column, row, data); -} - -/* - * Sets the width of a column in the container. - * Parameters: - * handle: Handle to window (widget) of container. - * column: Zero based column of width being set. - * width: Width of column in pixels. - */ -void API dw_container_set_column_width(HWND handle, int column, int width) -{ - ListView_SetColumnWidth(handle, column, width); -} - -/* - * Sets the title 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. - * title: String title of the item. - */ -void API dw_container_set_row_title(void *pointer, int row, char *title) -{ - LV_ITEM lvi; - HWND container = (HWND)pointer; - - lvi.iItem = row; - lvi.iSubItem = 0; - lvi.mask = LVIF_PARAM; - lvi.lParam = (LPARAM)title; - - if(!ListView_SetItem(container, &lvi) && lvi.lParam) - lvi.lParam = 0; - -} - -/* - * Sets the title of a row in the container. - * Parameters: - * handle: Handle to the container window (widget). - * pointer: Pointer to the allocated memory in dw_container_alloc(). - * rowcount: The number of rows to be inserted. - */ -void API dw_container_insert(HWND handle, void *pointer, int rowcount) -{ - ShowWindow(handle, SW_SHOW); -} - -/* - * Removes all rows from a container. - * Parameters: - * handle: Handle to the window (widget) to be cleared. - * redraw: TRUE to cause the container to redraw immediately. - */ -void API dw_container_clear(HWND handle, int redraw) -{ - ListView_DeleteAllItems(handle); -} - -/* - * Removes the first x rows from a container. - * Parameters: - * handle: Handle to the window (widget) to be deleted from. - * rowcount: The number of rows to be deleted. - */ -void API dw_container_delete(HWND handle, int rowcount) -{ - int z; - - for(z=0;z<rowcount;z++) - { - ListView_DeleteItem(handle, 0); - } -} - -/* - * Scrolls container up or down. - * Parameters: - * handle: Handle to the window (widget) to be scrolled. - * direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or - * DW_SCROLL_BOTTOM. (rows is ignored for last two) - * rows: The number of rows to be scrolled. - */ -void API dw_container_scroll(HWND handle, int direction, long rows) -{ - switch(direction) - { - case DW_SCROLL_TOP: - ListView_Scroll(handle, 0, -10000000); - break; - case DW_SCROLL_BOTTOM: - ListView_Scroll(handle, 0, 10000000); - break; - } -} - -/* - * Starts a new query of a container. - * Parameters: - * handle: Handle to the window (widget) to be queried. - * flags: If this parameter is DW_CRA_SELECTED it will only - * return items that are currently selected. Otherwise - * it will return all records in the container. - */ -char * API dw_container_query_start(HWND handle, unsigned long flags) -{ - LV_ITEM lvi; - - _index = ListView_GetNextItem(handle, -1, flags); - - if(_index == -1) - return NULL; - - memset(&lvi, 0, sizeof(LV_ITEM)); - - lvi.iItem = _index; - lvi.mask = LVIF_PARAM; - - ListView_GetItem(handle, &lvi); - - return (char *)lvi.lParam; -} - -/* - * Continues an existing query of a container. - * Parameters: - * handle: Handle to the window (widget) to be queried. - * flags: If this parameter is DW_CRA_SELECTED it will only - * return items that are currently selected. Otherwise - * it will return all records in the container. - */ -char * API dw_container_query_next(HWND handle, unsigned long flags) -{ - LV_ITEM lvi; - - _index = ListView_GetNextItem(handle, _index, flags); - - if(_index == -1) - return NULL; - - memset(&lvi, 0, sizeof(LV_ITEM)); - - lvi.iItem = _index; - lvi.mask = LVIF_PARAM; - - ListView_GetItem(handle, &lvi); - - return (char *)lvi.lParam; -} - -/* - * 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(HWND handle, char *text) -{ - int index = ListView_GetNextItem(handle, -1, LVNI_ALL); - - while(index != -1) - { - LV_ITEM lvi; - - memset(&lvi, 0, sizeof(LV_ITEM)); - - lvi.iItem = index; - lvi.mask = LVIF_PARAM; - - ListView_GetItem(handle, &lvi); - - if((char *)lvi.lParam == text) - { - RECT viewport, item; - - ListView_SetItemState(handle, index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); - ListView_EnsureVisible(handle, index, TRUE); - return; - } - - 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(HWND handle, char *text) -{ - int index = ListView_GetNextItem(handle, -1, LVNI_ALL); - - while(index != -1) - { - LV_ITEM lvi; - - memset(&lvi, 0, sizeof(LV_ITEM)); - - lvi.iItem = index; - lvi.mask = LVIF_PARAM; - - ListView_GetItem(handle, &lvi); - - if((char *)lvi.lParam == text) - { - ListView_DeleteItem(handle, index); - return; - } - - index = ListView_GetNextItem(handle, index, LVNI_ALL); - } -} - -/* - * Optimizes the column widths so that all data is visible. - * Parameters: - * handle: Handle to the window (widget) to be optimized. - */ -void API dw_container_optimize(HWND handle) -{ - ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - ULONG *flags; - LV_ITEM lvi; - - if(cinfo && cinfo->columns == 1) - { - ListView_SetColumnWidth(handle, 0, LVSCW_AUTOSIZE); - } - else if(cinfo && cinfo->columns > 1) - { - int z, index; - ULONG *flags = cinfo->flags, *columns = calloc(sizeof(ULONG), cinfo->columns); - char *text = malloc(1024); - - /* Initialize with sizes of column labels */ - for(z=0;z<cinfo->columns;z++) - { - if(flags[z] & DW_CFA_BITMAPORICON) - columns[z] = 5; - else - { - LVCOLUMN lvc; - - lvc.mask = LVCF_TEXT; - lvc.cchTextMax = 1023; - lvc.pszText = text; - - if(ListView_GetColumn(handle, z, &lvc)) - columns[z] = ListView_GetStringWidth(handle, lvc.pszText); - - if(flags[z] & DW_CFA_RESERVED) - columns[z] += 20; - } - } - - index = ListView_GetNextItem(handle, -1, LVNI_ALL); - - /* Query all the item texts */ - while(index != -1) - { - for(z=0;z<cinfo->columns;z++) - { - LV_ITEM lvi; - - memset(&lvi, 0, sizeof(LV_ITEM)); - - lvi.iItem = index; - lvi.iSubItem = z; - lvi.mask = LVIF_TEXT; - lvi.cchTextMax = 1023; - lvi.pszText = text; - - if(ListView_GetItem(handle, &lvi)) - { - int width = ListView_GetStringWidth(handle, lvi.pszText); - if(width > columns[z]) - { - if(z == 0) - columns[z] = width + 20; - else - columns[z] = width; - } - } - } - - index = ListView_GetNextItem(handle, index, LVNI_ALL); - } - - /* Set the new sizes */ - for(z=0;z<cinfo->columns;z++) - ListView_SetColumnWidth(handle, z, columns[z] + 16); - - free(columns); - free(text); - } -} - -/* - * Inserts an icon into the taskbar. - * Parameters: - * handle: Window handle that will handle taskbar icon messages. - * icon: Icon handle to display in the taskbar. - * bubbletext: Text to show when the mouse is above the icon. - */ -void dw_taskbar_insert(HWND handle, unsigned long icon, char *bubbletext) -{ - NOTIFYICONDATA tnid; - - tnid.cbSize = sizeof(NOTIFYICONDATA); - tnid.hWnd = handle; - tnid.uID = icon; - tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; - tnid.uCallbackMessage = WM_USER+2; - tnid.hIcon = (HICON)icon; - if(bubbletext) - strncpy(tnid.szTip, bubbletext, sizeof(tnid.szTip)); - else - tnid.szTip[0] = 0; - - Shell_NotifyIcon(NIM_ADD, &tnid); -} - -/* - * Deletes an icon from the taskbar. - * Parameters: - * handle: Window handle that was used with dw_taskbar_insert(). - * icon: Icon handle that was used with dw_taskbar_insert(). - */ -void dw_taskbar_delete(HWND handle, unsigned long icon) -{ - NOTIFYICONDATA tnid; - - tnid.cbSize = sizeof(NOTIFYICONDATA); - tnid.hWnd = handle; - tnid.uID = icon; - - Shell_NotifyIcon(NIM_DELETE, &tnid); -} - -/* - * Creates a rendering context widget (window) to be packed. - * Parameters: - * id: An id to be used with dw_window_from_id. - * Returns: - * A handle to the widget or NULL on failure. - */ -HWND API dw_render_new(unsigned long id) -{ - Box *newbox = calloc(sizeof(Box), 1); - HWND tmp = CreateWindow(ObjectClassName, - "", - WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - newbox->pad = 0; - newbox->type = 0; - newbox->count = 0; - newbox->grouphwnd = (HWND)NULL; - newbox->cinfo.pOldProc = SubclassWindow(tmp, _rendwndproc); - newbox->cinfo.fore = newbox->cinfo.back = -1; - - SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)newbox); - return tmp; -} - -/* Sets the current foreground drawing color. - * Parameters: - * red: red value. - * green: green value. - * blue: blue value. - */ -void API dw_color_foreground_set(unsigned long value) -{ - int threadid = dw_thread_id(); - - if(threadid < 0 || threadid >= THREAD_LIMIT) - threadid = 0; - - value = _internal_color(value); - - DeleteObject(_hPen[threadid]); - DeleteObject(_hBrush[threadid]); - _foreground[threadid] = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value)); - _hPen[threadid] = CreatePen(PS_SOLID, 1, _foreground[threadid]); - _hBrush[threadid] = CreateSolidBrush(_foreground[threadid]); -} - -/* Sets the current background drawing color. - * Parameters: - * red: red value. - * green: green value. - * blue: blue value. - */ -void API dw_color_background_set(unsigned long value) -{ - int threadid = dw_thread_id(); - - if(threadid < 0 || threadid >= THREAD_LIMIT) - threadid = 0; - - value = _internal_color(value); - - if(value == DW_RGB_TRANSPARENT) - _background[threadid] = DW_RGB_TRANSPARENT; - else - _background[threadid] = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value)); -} - -/* Draw a point on a window (preferably a render window). - * Parameters: - * handle: Handle to the window. - * pixmap: Handle to the pixmap. (choose only one of these) - * x: X coordinate. - * y: Y coordinate. - */ -void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y) -{ - HDC hdcPaint; - int threadid = dw_thread_id(); - - if(threadid < 0 || threadid >= THREAD_LIMIT) - threadid = 0; - - if(handle) - hdcPaint = GetDC(handle); - else if(pixmap) - hdcPaint = pixmap->hdc; - else - return; - - SetPixel(hdcPaint, x, y, _foreground[threadid]); - if(!pixmap) - ReleaseDC(handle, hdcPaint); -} - -/* Draw a line on a window (preferably a render window). - * Parameters: - * handle: Handle to the window. - * pixmap: Handle to the pixmap. (choose only one of these) - * x1: First X coordinate. - * y1: First Y coordinate. - * x2: Second X coordinate. - * y2: Second Y coordinate. - */ -void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2) -{ - HDC hdcPaint; - HPEN oldPen; - int threadid = dw_thread_id(); - - if(threadid < 0 || threadid >= THREAD_LIMIT) - threadid = 0; - - if(handle) - hdcPaint = GetDC(handle); - else if(pixmap) - hdcPaint = pixmap->hdc; - else - return; - - oldPen = SelectObject(hdcPaint, _hPen[threadid]); - MoveToEx(hdcPaint, x1, y1, NULL); - LineTo(hdcPaint, x2, y2); - SelectObject(hdcPaint, oldPen); - /* For some reason Win98 (at least) fails - * to draw the last pixel. So I do it myself. - */ - SetPixel(hdcPaint, x2, y2, _foreground[threadid]); - if(!pixmap) - ReleaseDC(handle, hdcPaint); -} - -/* Draw a rectangle on a window (preferably a render window). - * Parameters: - * handle: Handle to the window. - * pixmap: Handle to the pixmap. (choose only one of these) - * x: X coordinate. - * y: Y coordinate. - * width: Width of rectangle. - * height: Height of rectangle. - */ -void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height) -{ - HDC hdcPaint; - HPEN oldPen; - HBRUSH oldBrush; - RECT Rect; - int threadid = dw_thread_id(); - - if(threadid < 0 || threadid >= THREAD_LIMIT) - threadid = 0; - - if(handle) - hdcPaint = GetDC(handle); - else if(pixmap) - hdcPaint = pixmap->hdc; - else - return; - - SetRect(&Rect, x, y, x + width , y + height ); - if(fill) - FillRect(hdcPaint, &Rect, _hBrush[threadid]); - else - FrameRect(hdcPaint, &Rect, _hBrush[threadid]); - if(!pixmap) - ReleaseDC(handle, hdcPaint); -} - -/* Draw text on a window (preferably a render window). - * Parameters: - * handle: Handle to the window. - * pixmap: Handle to the pixmap. (choose only one of these) - * x: X coordinate. - * y: Y coordinate. - * text: Text to be displayed. - */ -void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text) -{ - HDC hdc; - int size = 9, z, mustdelete = 0; - HFONT hFont = 0, oldFont = 0; - int threadid = dw_thread_id(); - ColorInfo *cinfo; - - if(threadid < 0 || threadid >= THREAD_LIMIT) - threadid = 0; - - if(handle) - hdc = GetDC(handle); - else if(pixmap) - hdc = pixmap->hdc; - else - return; - - if(handle) - cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - else - cinfo = (ColorInfo *)GetWindowLongPtr(pixmap->handle, GWLP_USERDATA); - - if(cinfo) - { - hFont = _acquire_font(handle, cinfo->fontname); - mustdelete = 1; - } - - if(hFont) - oldFont = SelectObject(hdc, hFont); - SetTextColor(hdc, _foreground[threadid]); - if(_background[threadid] == DW_RGB_TRANSPARENT) - SetBkMode(hdc, TRANSPARENT); - else - { - SetBkMode(hdc, OPAQUE); - SetBkColor(hdc, _background[threadid]); - } - TextOut(hdc, x, y, text, strlen(text)); - if(oldFont) - SelectObject(hdc, oldFont); - if(mustdelete) - DeleteObject(hFont); - if(!pixmap) - ReleaseDC(handle, hdc); -} - -/* Query the width and height of a text string. - * Parameters: - * handle: Handle to the window. - * pixmap: Handle to the pixmap. (choose only one of these) - * text: Text to be queried. - * width: Pointer to a variable to be filled in with the width. - * height Pointer to a variable to be filled in with the height. - */ -void API dw_font_text_extents(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height) -{ - HDC hdc; - int mustdelete = 0; - HFONT hFont = NULL, oldFont; - SIZE sz; - - if(handle) - hdc = GetDC(handle); - else if(pixmap) - hdc = pixmap->hdc; - else - return; - - { - ColorInfo *cinfo; - - if(handle) - cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); - else - cinfo = (ColorInfo *)GetWindowLongPtr(pixmap->handle, GWLP_USERDATA); - - if(cinfo) - { - hFont = _acquire_font(handle, cinfo->fontname); - mustdelete = 1; - } - } - oldFont = SelectObject(hdc, hFont); - - GetTextExtentPoint32(hdc, text, strlen(text), &sz); - - if(width) - *width = sz.cx; - - if(height) - *height = sz.cy; - - SelectObject(hdc, oldFont); - if(mustdelete) - DeleteObject(hFont); - if(!pixmap) - ReleaseDC(handle, hdc); -} - -/* Call this after drawing to the screen to make sure - * anything you have drawn is visible. - */ -void API dw_flush(void) -{ -} - -/* - * Creates a pixmap with given parameters. - * Parameters: - * handle: Window handle the pixmap is associated with. - * width: Width of the pixmap in pixels. - * height: Height of the pixmap in pixels. - * depth: Color depth of the pixmap. - * Returns: - * A handle to a pixmap or NULL on failure. - */ -HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth) -{ - HPIXMAP pixmap; - BITMAP bm; - HDC hdc; - - if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) - return NULL; - - hdc = GetDC(handle); - - pixmap->width = width; pixmap->height = height; - - pixmap->handle = handle; - pixmap->hbm = CreateCompatibleBitmap(hdc, width, height); - pixmap->hdc = CreateCompatibleDC(hdc); - - SelectObject(pixmap->hdc, pixmap->hbm); - - ReleaseDC(handle, hdc); - - return pixmap; -} - -/* - * Creates a pixmap from a file. - * Parameters: - * handle: Window handle the pixmap is associated with. - * filename: Name of the file, omit extention to have - * DW pick the appropriate file extension. - * (BMP on OS/2 or Windows, XPM on Unix) - * Returns: - * A handle to a pixmap or NULL on failure. - */ -HPIXMAP API dw_pixmap_new_from_file(HWND handle, char *filename) -{ - HPIXMAP pixmap; - BITMAP bm; - HDC hdc; - char *file = malloc(strlen(filename) + 5); - - if (!file || !(pixmap = calloc(1,sizeof(struct _hpixmap)))) - { - if(file) - free(file); - return NULL; - } - - strcpy(file, filename); - - /* check if we can read from this file (it exists and read permission) */ - if(access(file, 04) != 0) - { - /* Try with .bmp extention */ - strcat(file, ".bmp"); - if(access(file, 04) != 0) - { - free(pixmap); - free(file); - return NULL; - } - } - - hdc = GetDC(handle); - - pixmap->handle = handle; - pixmap->hbm = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); - - if(!pixmap->hbm) - { - free(file); - free(pixmap); - ReleaseDC(handle, hdc); - return NULL; - } - - pixmap->hdc = CreateCompatibleDC(hdc); - - GetObject(pixmap->hbm, sizeof(bm), &bm); - - pixmap->width = bm.bmWidth; pixmap->height = bm.bmHeight; - - SelectObject(pixmap->hdc, pixmap->hbm); - - ReleaseDC(handle, hdc); - - free(file); - - return pixmap; -} - -/* - * Creates a pixmap from internal resource graphic specified by id. - * Parameters: - * handle: Window handle the pixmap is associated with. - * id: Resource ID associated with requested pixmap. - * Returns: - * A handle to a pixmap or NULL on failure. - */ -HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id) -{ - HPIXMAP pixmap; - BITMAP bm; - HDC hdc; - - if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) - return NULL; - - hdc = GetDC(handle); - - - pixmap->hbm = LoadBitmap(DWInstance, MAKEINTRESOURCE(id)); - pixmap->hdc = CreateCompatibleDC(hdc); - - GetObject(pixmap->hbm, sizeof(BITMAP), (void *)&bm); - - pixmap->width = bm.bmWidth; pixmap->height = bm.bmHeight; - - SelectObject(pixmap->hdc, pixmap->hbm); - - ReleaseDC(handle, hdc); - - return pixmap; -} - -/* - * Destroys an allocated pixmap. - * Parameters: - * pixmap: Handle to a pixmap returned by - * dw_pixmap_new.. - */ -void API dw_pixmap_destroy(HPIXMAP pixmap) -{ - if(pixmap) - { - DeleteDC(pixmap->hdc); - DeleteObject(pixmap->hbm); - free(pixmap); - } -} - -/* - * Copies from one item to another. - * Parameters: - * dest: Destination window handle. - * destp: Destination pixmap. (choose only one). - * xdest: X coordinate of destination. - * ydest: Y coordinate of destination. - * width: Width of area to copy. - * height: Height of area to copy. - * src: Source window handle. - * srcp: Source pixmap. (choose only one). - * xsrc: X coordinate of source. - * ysrc: Y coordinate of source. - */ -void API dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc) -{ - HDC hdcdest; - HDC hdcsrc; - - if(dest) - hdcdest = GetDC(dest); - else if(destp) - hdcdest = destp->hdc; - else - return; - - if(src) - hdcsrc = GetDC(src); - else if(srcp) - hdcsrc = srcp->hdc; - else - return; - - BitBlt(hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, SRCCOPY); - - if(!destp) - ReleaseDC(dest, hdcdest); - if(!srcp) - ReleaseDC(src, hdcsrc); -} - -/* - * Emits a beep. - * Parameters: - * freq: Frequency. - * dur: Duration. - */ -void API dw_beep(int freq, int dur) -{ - Beep(freq, dur); -} - -/* Open a shared library and return a handle. - * Parameters: - * name: Base name of the shared library. - * handle: Pointer to a module handle, - * will be filled in with the handle. - */ -int API dw_module_load(char *name, HMOD *handle) -{ - if(!handle) - return -1; - - *handle = LoadLibrary(name); - return (NULL == *handle); -} - -/* Queries the address of a symbol within open handle. - * Parameters: - * handle: Module handle returned by dw_module_load() - * name: Name of the symbol you want the address of. - * func: A pointer to a function pointer, to obtain - * the address. - */ -int API dw_module_symbol(HMOD handle, char *name, void**func) -{ - if(!func || !name) - return -1; - - if(0 == strlen(name)) - return -1; - - *func = (void*)GetProcAddress(handle, name); - return (NULL == *func); -} - -/* Frees the shared library previously opened. - * Parameters: - * handle: Module handle returned by dw_module_load() - */ -int API dw_module_close(HMOD handle) -{ - return FreeLibrary(handle); -} - -/* - * Returns the handle to an unnamed mutex semaphore. - */ -HMTX API dw_mutex_new(void) -{ - return (HMTX)CreateMutex(NULL, FALSE, NULL); -} - -/* - * Closes a semaphore created by dw_mutex_new(). - * Parameters: - * mutex: The handle to the mutex returned by dw_mutex_new(). - */ -void API dw_mutex_close(HMTX mutex) -{ - CloseHandle((HANDLE)mutex); -} - -/* - * Tries to gain access to the semaphore, if it can't it blocks. - * Parameters: - * mutex: The handle to the mutex returned by dw_mutex_new(). - */ -void API dw_mutex_lock(HMTX mutex) -{ - if(_dwtid == dw_thread_id()) - { - int rc = WaitForSingleObject((HANDLE)mutex, 0); - - while(rc == WAIT_TIMEOUT) - { - dw_main_sleep(1); - rc = WaitForSingleObject((HANDLE)mutex, 0); - } - } - else - WaitForSingleObject((HANDLE)mutex, INFINITE); -} - -/* - * Reliquishes the access to the semaphore. - * Parameters: - * mutex: The handle to the mutex returned by dw_mutex_new(). - */ -void API dw_mutex_unlock(HMTX mutex) -{ - ReleaseMutex((HANDLE)mutex); -} - -/* - * Returns the handle to an unnamed event semaphore. - */ -HEV API dw_event_new(void) -{ - return CreateEvent(NULL, TRUE, FALSE, NULL); -} - -/* - * Resets a semaphore created by dw_event_new(). - * Parameters: - * eve: The handle to the event returned by dw_event_new(). - */ -int API dw_event_reset(HEV eve) -{ - return ResetEvent(eve); -} - -/* - * Posts a semaphore created by dw_event_new(). Causing all threads - * waiting on this event in dw_event_wait to continue. - * Parameters: - * eve: The handle to the event returned by dw_event_new(). - */ -int API dw_event_post(HEV eve) -{ - return SetEvent(eve); -} - -/* - * Waits on a semaphore created by dw_event_new(), until the - * event gets posted or until the timeout expires. - * Parameters: - * eve: The handle to the event returned by dw_event_new(). - */ -int API dw_event_wait(HEV eve, unsigned long timeout) -{ - int rc; - - rc = WaitForSingleObject(eve, timeout); - if(rc == WAIT_OBJECT_0) - return 1; - if(rc == WAIT_ABANDONED) - return -1; - return 0; -} - -/* - * Closes a semaphore created by dw_event_new(). - * Parameters: - * eve: The handle to the event returned by dw_event_new(). - */ -int API dw_event_close(HEV *eve) -{ - if(eve) - return CloseHandle(*eve); - return FALSE; -} - -/* - * Creates a new thread with a starting point of func. - * Parameters: - * func: Function which will be run in the new thread. - * data: Parameter(s) passed to the function. - * stack: Stack size of new thread (OS/2 and Windows only). - */ -DWTID API dw_thread_new(void *func, void *data, int stack) -{ -#if defined(__CYGWIN__) - return 0; -#else - return (DWTID)_beginthread((void(*)(void *))func, stack, data); -#endif -} - -/* - * Ends execution of current thread immediately. - */ -void API dw_thread_end(void) -{ -#if !defined(__CYGWIN__) - _endthread(); -#endif -} - -/* - * Returns the current thread's ID. - */ -DWTID API dw_thread_id(void) -{ -#if defined(__CYGWIN__) - return 0; -#else - return (DWTID)GetCurrentThreadId(); -#endif -} - -/* - * 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) -{ - exit(exitcode); -} - -/* - * Creates a splitbar window (widget) with given parameters. - * Parameters: - * type: Value can be DW_VERT or DW_HORZ. - * topleft: Handle to the window to be top or left. - * bottomright: Handle to the window to be bottom or right. - * Returns: - * A handle to a splitbar window or NULL on failure. - */ -HWND API dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id) -{ - HWND tmp = CreateWindow(SplitbarClassName, - "", - WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, - 0,0,2000,1000, - DW_HWND_OBJECT, - (HMENU)id, - DWInstance, - NULL); - - if(tmp) - { - HWND tmpbox = dw_box_new(DW_VERT, 0); - 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); - - 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); - *percent = 50.0; - dw_window_set_data(tmp, "_dw_percent", (void *)percent); - dw_window_set_data(tmp, "_dw_type", (void *)type); - } - return tmp; -} - -/* - * Sets the position of a splitbar (pecentage). - * Parameters: - * handle: The handle to the splitbar returned by dw_splitbar_new(). - */ -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; - - if(mypercent) - *mypercent = percent; - - dw_window_get_pos_size(handle, NULL, NULL, &width, &height); - - _handle_splitbar_resize(handle, percent, type, width, height); -} - -/* - * Gets the position of a splitbar (pecentage). - * Parameters: - * handle: The handle to the splitbar returned by dw_splitbar_new(). - */ -float API dw_splitbar_get(HWND handle) -{ - float *percent = (float *)dw_window_get_data(handle, "_dw_percent"); - - if(percent) - return *percent; - return 0.0; -} - -/* - * Pack windows (widgets) into a box from the end (or bottom). - * Parameters: - * box: Window handle of the box to be packed into. - * item: Window handle of the item to be back. - * width: Width in pixels of the item or -1 to be self determined. - * height: Height in pixels of the item or -1 to be self determined. - * hsize: TRUE if the window (widget) should expand horizontally to fill space given. - * vsize: TRUE if the window (widget) should expand vertically to fill space given. - * pad: Number of pixels of padding around the item. - */ -void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) -{ - Box *thisbox; - - /* - * If you try and pack an item into itself VERY bad things can happen; like at least an - * infinite loop on GTK! Lets be safe! - */ - if(box == item) - { - dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!",box,item); - return; - } - - thisbox = (Box *)GetWindowLongPtr(box, GWLP_USERDATA); - if(thisbox) - { - int z; - Item *tmpitem, *thisitem = thisbox->items; - char tmpbuf[100]; - - tmpitem = malloc(sizeof(Item)*(thisbox->count+1)); - - for(z=0;z<thisbox->count;z++) - { - tmpitem[z+1] = thisitem[z]; - } - - GetClassName(item, tmpbuf, 99); - - if(vsize && !height) - height = 1; - if(hsize && !width) - width = 1; - - if(strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1)==0) - tmpitem[0].type = TYPEBOX; - else - { - if ( width == 0 && hsize == FALSE ) - dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item); - if ( height == 0 && vsize == FALSE ) - dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item); - - tmpitem[0].type = TYPEITEM; - } - - tmpitem[0].hwnd = item; - tmpitem[0].origwidth = tmpitem[0].width = width; - tmpitem[0].origheight = tmpitem[0].height = height; - tmpitem[0].pad = pad; - if(hsize) - tmpitem[0].hsize = SIZEEXPAND; - else - tmpitem[0].hsize = SIZESTATIC; - - if(vsize) - tmpitem[0].vsize = SIZEEXPAND; - else - tmpitem[0].vsize = SIZESTATIC; - - thisbox->items = tmpitem; - - if(thisbox->count) - free(thisitem); - - thisbox->count++; - - SetParent(item, box); - if(strncmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0) - { - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(item, GWLP_USERDATA); - - if(cinfo) - { - SetParent(cinfo->buddy, box); - ShowWindow(cinfo->buddy, SW_SHOW); - SendMessage(item, UDM_SETBUDDY, (WPARAM)cinfo->buddy, 0); - } - } - } -} - -/* - * Sets the default focus item for a window/dialog. - * Parameters: - * window: Toplevel window or dialog. - * defaultitem: Handle to the dialog item to be default. - */ -void API dw_window_default(HWND window, HWND defaultitem) -{ - Box *thisbox = (Box *)GetWindowLongPtr(window, GWLP_USERDATA); - - if(thisbox) - thisbox->defaultitem = defaultitem; -} - -/* - * Sets window to click the default dialog item when an ENTER is pressed. - * Parameters: - * window: Window (widget) to look for the ENTER press. - * next: Window (widget) to move to next (or click) - */ -void API dw_window_click_default(HWND window, HWND next) -{ - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(window, GWLP_USERDATA); - - if(cinfo) - cinfo->clickdefault = next; -} - -/* - * Returns some information about the current operating environment. - * Parameters: - * env: Pointer to a DWEnv struct. - */ -void API dw_environment_query(DWEnv *env) -{ - if(!env) - return; - - /* Get the Windows version. */ - - env->MajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); - env->MinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); - - /* Get the build number for Windows NT/Windows 2000. */ - - env->MinorBuild = 0; - - if (dwVersion < 0x80000000) - { - if(env->MajorVersion == 5 && env->MinorVersion == 1) - strcpy(env->osName, "Windows XP"); - else if(env->MajorVersion == 5 && env->MinorVersion == 0) - strcpy(env->osName, "Windows 2000"); - else - strcpy(env->osName, "Windows NT"); - - env->MajorBuild = (DWORD)(HIWORD(dwVersion)); - } - else - { - strcpy(env->osName, "Windows 95/98/ME"); - env->MajorBuild = 0; - } - - strcpy(env->buildDate, __DATE__); - strcpy(env->buildTime, __TIME__); - env->DWMajorVersion = DW_MAJOR_VERSION; - env->DWMinorVersion = DW_MINOR_VERSION; - env->DWSubVersion = DW_SUB_VERSION; -} - -/* - * Opens a file dialog and queries user selection. - * Parameters: - * title: Title bar text for dialog. - * defpath: The default path of the open dialog. - * ext: Default file extention. - * flags: DW_FILE_OPEN or DW_FILE_SAVE or DW_DIRECTORY_OPEN. - * Returns: - * NULL on error. A malloced buffer containing - * the file path on success. - * - */ -char * API dw_file_browse(char *title, char *defpath, char *ext, int flags) -{ - OPENFILENAME of; - char filenamebuf[1001] = ""; - int rc; - - BROWSEINFO bi; - TCHAR szDir[MAX_PATH]; - LPITEMIDLIST pidl; - LPMALLOC pMalloc; - - if(flags==DW_DIRECTORY_OPEN) - { - if (SUCCEEDED(SHGetMalloc(&pMalloc))) - { - ZeroMemory(&bi,sizeof(bi)); - bi.hwndOwner = NULL; - bi.pszDisplayName = 0; - bi.pidlRoot = 0; - bi.lpszTitle = title; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT; - bi.lpfn = NULL; /*BrowseCallbackProc*/ - - pidl = SHBrowseForFolder(&bi); - if (pidl) - { - if (SHGetPathFromIDList(pidl,szDir)) - { - strcpy(filenamebuf,szDir); - } - - // In C++: pMalloc->Free(pidl); pMalloc->Release(); - pMalloc->lpVtbl->Free(pMalloc,pidl); - pMalloc->lpVtbl->Release(pMalloc); - return strdup(filenamebuf); - } - } - } - else - { - if(ext) - { - strcpy(filenamebuf, "*."); - strcat(filenamebuf, ext); - } - - memset(&of, 0, sizeof(OPENFILENAME)); - - of.lStructSize = sizeof(OPENFILENAME); - of.hwndOwner = HWND_DESKTOP; - of.hInstance = DWInstance; - of.lpstrInitialDir = defpath; - of.lpstrTitle = title; - of.lpstrFile = filenamebuf; - of.nMaxFile = 1000; - of.lpstrDefExt = ext; - of.Flags = 0; - - if(flags & DW_FILE_SAVE) - rc = GetSaveFileName(&of); - else - rc = GetOpenFileName(&of); - - if(rc) - return strdup(of.lpstrFile); - } - return NULL; -} - -/* - * Execute and external program in a seperate session. - * Parameters: - * program: Program name with optional path. - * type: Either DW_EXEC_CON or DW_EXEC_GUI. - * params: An array of pointers to string arguements. - * Returns: - * -1 on error. - */ -int API dw_exec(char *program, int type, char **params) -{ - char **newparams; - int retcode, count = 0, z; - - while(params[count]) - { - count++; - } - - newparams = (char **)malloc(sizeof(char *) * (count+1)); - - for(z=0;z<count;z++) - { - newparams[z] = malloc(strlen(params[z])+3); - strcpy(newparams[z], "\""); - strcat(newparams[z], params[z]); - strcat(newparams[z], "\""); - } - newparams[count] = NULL; - - retcode = spawnvp(P_NOWAIT, program, newparams); - - for(z=0;z<count;z++) - { - free(newparams[z]); - } - free(newparams); - - return retcode; -} - -/* - * Loads a web browser pointed at the given URL. - * Parameters: - * url: Uniform resource locator. - */ -int API dw_browse(char *url) -{ - char *browseurl = url; - int retcode; - - if(strlen(url) > 7 && strncmp(url, "file://", 7) == 0) - { - int len, z; - - browseurl = &url[7]; - len = strlen(browseurl); - - for(z=0;z<len;z++) - { - if(browseurl[z] == '|') - browseurl[z] = ':'; - if(browseurl[z] == '/') - browseurl[z] = '\\'; - } - } - - retcode = (int)ShellExecute(NULL, "open", browseurl, NULL, NULL, SW_SHOWNORMAL); - if(retcode<33 && retcode != 2) - return -1; - return 1; -} - -/* - * Returns a pointer to a static buffer which containes the - * current user directory. Or the root directory (C:\ on - * OS/2 and Windows). - */ -char * API dw_user_dir(void) -{ - static char _user_dir[1024] = ""; - - if(!_user_dir[0]) - { - /* Figure out how to do this the "Windows way" */ - char *home = getenv("HOME"); - - if(home) - strcpy(_user_dir, home); - else - strcpy(_user_dir, "C:\\"); - } - return _user_dir; -} - -/* - * Call a function from the window (widget)'s context. - * Parameters: - * handle: Window handle of the widget. - * function: Function pointer to be called. - * data: Pointer to the data to be passed to the function. - */ -void API dw_window_function(HWND handle, void *function, void *data) -{ - SendMessage(handle, WM_USER, (WPARAM)function, (LPARAM)data); -} - -/* Functions for managing the user data lists that are associated with - * a given window handle. Used in dw_window_set_data() and - * dw_window_get_data(). - */ -UserData *_find_userdata(UserData **root, char *varname) -{ - UserData *tmp = *root; - - while(tmp) - { - if(stricmp(tmp->varname, varname) == 0) - return tmp; - tmp = tmp->next; - } - return NULL; -} - -int _new_userdata(UserData **root, char *varname, void *data) -{ - UserData *new = _find_userdata(root, varname); - - if(new) - { - new->data = data; - return TRUE; - } - else - { - new = malloc(sizeof(UserData)); - if(new) - { - new->varname = strdup(varname); - new->data = data; - - new->next = NULL; - - if (!*root) - *root = new; - else - { - UserData *prev = NULL, *tmp = *root; - while(tmp) - { - prev = tmp; - tmp = tmp->next; - } - if(prev) - prev->next = new; - else - *root = new; - } - return TRUE; - } - } - return FALSE; -} - -int _remove_userdata(UserData **root, char *varname, int all) -{ - UserData *prev = NULL, *tmp = *root; - - while(tmp) - { - if(all || stricmp(tmp->varname, varname) == 0) - { - if(!prev) - { - *root = tmp->next; - free(tmp->varname); - free(tmp); - if(!all) - return 0; - tmp = *root; - } - else - { - /* If all is true we should - * never get here. - */ - prev->next = tmp->next; - free(tmp->varname); - free(tmp); - return 0; - } - } - else - { - prev = tmp; - tmp = tmp->next; - } - } - return 0; -} - -/* - * Add a named user data item to a window handle. - * Parameters: - * window: Window handle of signal to be called back. - * dataname: A string pointer identifying which signal to be hooked. - * data: User data to be passed to the handler function. - */ -void API dw_window_set_data(HWND window, char *dataname, void *data) -{ - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(window, GWLP_USERDATA); - - if(!cinfo) - { - if(!dataname) - return; - - cinfo = calloc(1, sizeof(ColorInfo)); - cinfo->fore = cinfo->back = -1; - SetWindowLongPtr(window, GWLP_USERDATA, (LONG_PTR)cinfo); - } - - if(cinfo) - { - if(data) - _new_userdata(&(cinfo->root), dataname, data); - else - { - if(dataname) - _remove_userdata(&(cinfo->root), dataname, FALSE); - else - _remove_userdata(&(cinfo->root), NULL, TRUE); - } - } -} - -/* - * Gets a named user data item to a window handle. - * Parameters: - * window: Window handle of signal to be called back. - * dataname: A string pointer identifying which signal to be hooked. - * data: User data to be passed to the handler function. - */ -void * API dw_window_get_data(HWND window, char *dataname) -{ - ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(window, GWLP_USERDATA); - - if(cinfo && cinfo->root && dataname) - { - UserData *ud = _find_userdata(&(cinfo->root), dataname); - if(ud) - return ud->data; - } - return NULL; -} - -/* - * Add a callback to a timer event. - * Parameters: - * interval: Milliseconds to delay between calls. - * sigfunc: The pointer to the function to be used as the callback. - * data: User data to be passed to the handler function. - * Returns: - * Timer ID for use with dw_timer_disconnect(), 0 on error. - */ -int API dw_timer_connect(int interval, void *sigfunc, void *data) -{ - if(sigfunc) - { - int timerid = SetTimer(NULL, 0, interval, _TimerProc); - - if(timerid) - { - _new_signal(WM_TIMER, NULL, timerid, sigfunc, data); - return timerid; - } - } - return 0; -} - -/* - * Removes timer callback. - * Parameters: - * id: Timer ID returned by dw_timer_connect(). - */ -void API dw_timer_disconnect(int id) -{ - SignalHandler *prev = NULL, *tmp = Root; - - /* 0 is an invalid timer ID */ - if(!id) - return; - - KillTimer(NULL, id); - - while(tmp) - { - if(tmp->id == id) - { - if(prev) - { - prev->next = tmp->next; - free(tmp); - tmp = prev->next; - } - else - { - Root = tmp->next; - free(tmp); - tmp = Root; - } - } - else - { - prev = tmp; - tmp = tmp->next; - } - } -} - -/* - * Add a callback to a window event. - * 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. - * data: User data to be passed to the handler function. - */ -void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data) -{ - ULONG message = 0, id = 0; - - if(window && signame && sigfunc) - { - if(stricmp(signame, DW_SIGNAL_SET_FOCUS) == 0) - window = _normalize_handle(window); - - if((message = _findsigmessage(signame)) != 0) - { - /* Handle special case of the menu item */ - if(message == WM_COMMAND && window < (HWND)65536) - { - char buffer[15]; - HWND owner; - - sprintf(buffer, "_dw_id%d", (int)window); - owner = (HWND)dw_window_get_data(DW_HWND_OBJECT, buffer); - - if(owner) - { - id = (ULONG)window; - window = owner; - dw_window_set_data(DW_HWND_OBJECT, buffer, 0); - } - else - { - /* If it is a popup menu clear all entries */ - dw_signal_disconnect_by_window(window); - } - } - _new_signal(message, window, id, sigfunc, data); - } - } -} - -/* - * Removes callbacks for a given window with given name. - * Parameters: - * window: Window handle of callback to be removed. - */ -void API dw_signal_disconnect_by_name(HWND window, char *signame) -{ - SignalHandler *prev = NULL, *tmp = Root; - ULONG message; - - if(!window || !signame || (message = _findsigmessage(signame)) == 0) - return; - - while(tmp) - { - if(tmp->window == window && tmp->message == message) - { - if(prev) - { - prev->next = tmp->next; - free(tmp); - tmp = prev->next; - } - else - { - Root = tmp->next; - free(tmp); - tmp = Root; - } - } - else - { - prev = tmp; - tmp = tmp->next; - } - } -} - -/* - * Removes all callbacks for a given window. - * Parameters: - * window: Window handle of callback to be removed. - */ -void API dw_signal_disconnect_by_window(HWND window) -{ - SignalHandler *prev = NULL, *tmp = Root; - - while(tmp) - { - if(tmp->window == window) - { - if(prev) - { - prev->next = tmp->next; - free(tmp); - tmp = prev->next; - } - else - { - Root = tmp->next; - free(tmp); - tmp = Root; - } - } - else - { - prev = tmp; - tmp = tmp->next; - } - } -} - -/* - * Removes all callbacks for a given window with specified data. - * Parameters: - * window: Window handle of callback to be removed. - * data: Pointer to the data to be compared against. - */ -void API dw_signal_disconnect_by_data(HWND window, void *data) -{ - SignalHandler *prev = NULL, *tmp = Root; - - while(tmp) - { - if(tmp->window == window && tmp->data == data) - { - if(prev) - { - prev->next = tmp->next; - free(tmp); - tmp = prev->next; - } - else - { - Root = tmp->next; - free(tmp); - tmp = Root; - } - } - else - { - prev = tmp; - tmp = tmp->next; - } - } -} - +/* + * Dynamic Windows: + * A GTK like implementation of the Win32 GUI + * + * (C) 2000-2011 Brian Smith <brian@dbsoft.org> + * (C) 2003-2005 Mark Hessling <m.hessling@qut.edu.au> + * + */ +#define _WIN32_IE 0x0500 +#define WINVER 0x500 +#include <windows.h> +#include <windowsx.h> +#include <commctrl.h> +#include <shlwapi.h> +#include <shlobj.h> +#include <userenv.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <process.h> +#include <time.h> +#include <math.h> +#include "dw.h" +#include "XBrowseForFolder.h" + +#ifdef GDIPLUS +/* GDI+ Headers are not C compatible... so define what we need here instead */ +struct GdiplusStartupInput +{ + UINT32 GdiplusVersion; + void *DebugEventCallback; + BOOL SuppressBackgroundThread; + BOOL SuppressExternalCodecs; +}; + +typedef enum { + Ok = 0, + GenericError = 1, + InvalidParameter = 2, + OutOfMemory = 3, + ObjectBusy = 4, + InsufficientBuffer = 5, + NotImplemented = 6, + Win32Error = 7, + WrongState = 8, + Aborted = 9, + FileNotFound = 10, + ValueOverflow = 11, + AccessDenied = 12, + UnknownImageFormat = 13, + FontFamilyNotFound = 14, + FontStyleNotFound = 15, + NotTrueTypeFont = 16, + UnsupportedGdiplusVersion = 17, + GdiplusNotInitialized = 18, + PropertyNotFound = 19, + PropertyNotSupported = 20, + ProfileNotFound = 21 +} Status; + +Status WINAPI GdipCreateBitmapFromFile(const WCHAR* filename, void **bitmap); +Status WINAPI GdipCreateHBITMAPFromBitmap(void *bitmap, HBITMAP* hbmReturn, DWORD background); +Status WINAPI GdipCreateHICONFromBitmap(void *bitmap, HICON *hbmReturn); +Status WINAPI GdipDisposeImage(void *image); +Status WINAPI GdipGetImagePixelFormat(void *image, INT *format); +Status WINAPI GdiplusStartup(ULONG_PTR *token, const struct GdiplusStartupInput *input, void *output); +VOID WINAPI GdiplusShutdown(ULONG_PTR token); + +/* Pixel format information */ +#define PixelFormatIndexed 0x00010000 +#define PixelFormatGDI 0x00020000 +#define PixelFormatAlpha 0x00040000 +#define PixelFormatPAlpha 0x00080000 +#define PixelFormatExtended 0x00100000 +#define PixelFormatCanonical 0x00200000 + +#define PixelFormatUndefined 0 +#define PixelFormatDontCare 0 + +#define PixelFormat1bppIndexed (1 | ( 1 << 8) | PixelFormatIndexed | PixelFormatGDI) +#define PixelFormat4bppIndexed (2 | ( 4 << 8) | PixelFormatIndexed | PixelFormatGDI) +#define PixelFormat8bppIndexed (3 | ( 8 << 8) | PixelFormatIndexed | PixelFormatGDI) +#define PixelFormat16bppGrayScale (4 | (16 << 8) | PixelFormatExtended) +#define PixelFormat16bppRGB555 (5 | (16 << 8) | PixelFormatGDI) +#define PixelFormat16bppRGB565 (6 | (16 << 8) | PixelFormatGDI) +#define PixelFormat16bppARGB1555 (7 | (16 << 8) | PixelFormatAlpha | PixelFormatGDI) +#define PixelFormat24bppRGB (8 | (24 << 8) | PixelFormatGDI) +#define PixelFormat32bppRGB (9 | (32 << 8) | PixelFormatGDI) +#define PixelFormat32bppARGB (10 | (32 << 8) | PixelFormatAlpha | PixelFormatGDI | PixelFormatCanonical) +#define PixelFormat32bppPARGB (11 | (32 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatGDI) +#define PixelFormat48bppRGB (12 | (48 << 8) | PixelFormatExtended) +#define PixelFormat64bppARGB (13 | (64 << 8) | PixelFormatAlpha | PixelFormatCanonical | PixelFormatExtended) +#define PixelFormat64bppPARGB (14 | (64 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatExtended) +#define PixelFormat32bppCMYK (15 | (32 << 8)) + +/* Token to the GDI+ Instance */ +ULONG_PTR gdiplusToken; +#endif + +/* + * MinGW (as at 3.2.3) doesn't have MIM_MENUDATA + * so #define it here + */ + +#if !defined( MIM_MENUDATA ) +# define MIM_MENUDATA 0x00000008 +#endif + +HWND popup = (HWND)NULL, DW_HWND_OBJECT = (HWND)NULL; + +HINSTANCE DWInstance = NULL; + +DWORD dwVersion = 0, dwComctlVer = 0; +DWTID _dwtid = -1; +SECURITY_DESCRIPTOR _dwsd; + +#define PACKVERSION(major,minor) MAKELONG(minor,major) + +#define IS_XPPLUS (dwComctlVer >= PACKVERSION(5,82)) +#define IS_VISTAPLUS (dwComctlVer >= PACKVERSION(6,10)) + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +/* + * 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 + * We use _tempnam() which uses TMP env variable by default. It can be passed + * an alternate temporary directory if TMP is not set, so we get the value + * of TEMP and store it here. + */ +static char _dw_alternate_temp_dir[MAX_PATH+1]; + +int main(int argc, char *argv[]); + +#define ICON_INDEX_LIMIT 200 +HICON lookup[200]; +HIMAGELIST hSmall = 0, hLarge = 0; + +/* Special flag used for internal tracking */ +#define DW_CFA_RESERVED (1 << 30) + +DWORD _foreground; +DWORD _background; +DWORD _hPen; +DWORD _hBrush; + +BYTE _red[] = { 0x00, 0xbb, 0x00, 0xaa, 0x00, 0xbb, 0x00, 0xaa, 0x77, + 0xff, 0x00, 0xee, 0x00, 0xff, 0x00, 0xff, 0xaa, 0x00 }; +BYTE _green[] = { 0x00, 0x00, 0xbb, 0xaa, 0x00, 0x00, 0xbb, 0xaa, 0x77, + 0x00, 0xff, 0xee, 0x00, 0x00, 0xee, 0xff, 0xaa, 0x00 }; +BYTE _blue[] = { 0x00, 0x00, 0x00, 0x00, 0xcc, 0xbb, 0xbb, 0xaa, 0x77, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xee, 0xff, 0xaa, 0x00}; + +HBRUSH _colors[18]; + +static int screenx, screeny; +HFONT _DefaultFont = NULL; + +LRESULT CALLBACK _browserWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +void _resize_notebook_page(HWND handle, int pageid); +void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y); +int _lookup_icon(HWND handle, HICON hicon, int type); +HFONT _acquire_font(HWND handle, char *fontname); +void _click_default(HWND handle); +void _do_resize(Box *thisbox, int x, int y); + +typedef struct _sighandler +{ + struct _sighandler *next; + ULONG message; + HWND window; + int id; + void *signalfunction; + void *data; + +} SignalHandler; + +SignalHandler *Root = NULL; + +typedef struct +{ + ULONG message; + char name[30]; + +} SignalList; + +static int in_checkbox_handler = 0; + +/* List of signals and their equivilent Win32 message */ +#define SIGNALMAX 17 + +SignalList SignalTranslate[SIGNALMAX] = { + { WM_SIZE, DW_SIGNAL_CONFIGURE }, + { WM_CHAR, DW_SIGNAL_KEY_PRESS }, + { WM_LBUTTONDOWN, DW_SIGNAL_BUTTON_PRESS }, + { WM_LBUTTONUP, DW_SIGNAL_BUTTON_RELEASE }, + { WM_MOUSEMOVE, DW_SIGNAL_MOTION_NOTIFY }, + { WM_CLOSE, DW_SIGNAL_DELETE }, + { WM_PAINT, DW_SIGNAL_EXPOSE }, + { WM_COMMAND, DW_SIGNAL_CLICKED }, + { NM_DBLCLK, DW_SIGNAL_ITEM_ENTER }, + { NM_RCLICK, DW_SIGNAL_ITEM_CONTEXT }, + { LBN_SELCHANGE, DW_SIGNAL_LIST_SELECT }, + { TVN_SELCHANGED, DW_SIGNAL_ITEM_SELECT }, + { WM_SETFOCUS, DW_SIGNAL_SET_FOCUS }, + { WM_VSCROLL, DW_SIGNAL_VALUE_CHANGED }, + { TCN_SELCHANGE, DW_SIGNAL_SWITCH_PAGE }, + { LVN_COLUMNCLICK, DW_SIGNAL_COLUMN_CLICK }, + { TVN_ITEMEXPANDED,DW_SIGNAL_TREE_EXPAND } +}; + +#ifdef BUILD_DLL +void Win32_Set_Instance(HINSTANCE hInstance) +{ + DWInstance = hInstance; +} +#else +char **_convertargs(int *count, char *start) +{ + char *tmp, *argstart, **argv; + int loc = 0, inquotes = 0; + + (*count) = 1; + + tmp = start; + + /* Count the number of entries */ + if(*start) + { + (*count)++; + + while(*tmp) + { + if(*tmp == '"' && inquotes) + inquotes = 0; + else if(*tmp == '"' && !inquotes) + inquotes = 1; + else if(*tmp == ' ' && !inquotes) + { + /* Push past any white space */ + while(*(tmp+1) == ' ') + tmp++; + /* If we aren't at the end of the command + * line increment the count. + */ + if(*(tmp+1)) + (*count)++; + } + tmp++; + } + } + + argv = (char **)malloc(sizeof(char *) * ((*count)+1)); + argv[0] = malloc(260); + GetModuleFileName(DWInstance, argv[0], 260); + + argstart = tmp = start; + + if(*start) + { + loc = 1; + + while(*tmp) + { + if(*tmp == '"' && inquotes) + { + *tmp = 0; + inquotes = 0; + } + else if(*tmp == '"' && !inquotes) + { + argstart = tmp+1; + inquotes = 1; + } + else if(*tmp == ' ' && !inquotes) + { + *tmp = 0; + argv[loc] = strdup(argstart); + + /* Push past any white space */ + while(*(tmp+1) == ' ') + tmp++; + + /* Move the start pointer */ + argstart = tmp+1; + + /* If we aren't at the end of the command + * line increment the count. + */ + if(*(tmp+1)) + loc++; + } + tmp++; + } + if(*argstart) + argv[loc] = strdup(argstart); + } + argv[loc+1] = NULL; + return argv; +} + +/* Ok this is a really big hack but what the hell ;) */ +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + char **argv; + int argc; + + DWInstance = hInstance; + + argv = _convertargs(&argc, lpCmdLine); + + return main(argc, argv); +} +#endif + +DWORD GetDllVersion(LPCTSTR lpszDllName) +{ + + HINSTANCE hinstDll; + DWORD dwVersion = 0; + + hinstDll = LoadLibrary(lpszDllName); + + if(hinstDll) + { + DLLGETVERSIONPROC pDllGetVersion; + + pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion"); + + /* Because some DLLs might not implement this function, you + * must test for it explicitly. Depending on the particular + * DLL, the lack of a DllGetVersion function can be a useful + * indicator of the version. + */ + if(pDllGetVersion) + { + DLLVERSIONINFO dvi; + HRESULT hr; + + ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + + hr = (*pDllGetVersion)(&dvi); + + if(SUCCEEDED(hr)) + { + dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion); + } + } + + FreeLibrary(hinstDll); + } + return dwVersion; +} + +#ifdef GDIPLUS +/* + * List those icons that have transparency first + * GDI+ List of supported formats: BMP, ICON, GIF, JPEG, Exif, PNG, TIFF, WMF, and EMF. + * Not sure if we should include all these or not... maybe we should add TIFF and GIF? + */ +#define NUM_EXTS 8 +char *image_exts[NUM_EXTS] = +{ + "", + ".png", + ".ico", + ".gif", + ".jpg", + ".jpeg", + ".tiff", + ".bmp" +}; + +/* Section for loading files of types besides BMP and ICO and return HBITMAP or HICON */ +void *_dw_load_gpbitmap( char *filename ) +{ + int found_ext = 0,i, wclen = (strlen(filename) + 6) * sizeof(wchar_t); + char *file = _alloca(strlen(filename) + 6); + wchar_t *wfile = _alloca(wclen); + void *image; + + /* Try various extentions */ + for ( i = 0; i < NUM_EXTS; i++ ) + { + strcpy( file, filename ); + strcat( file, image_exts[i] ); + if ( access( file, 04 ) == 0 ) + { + /* Convert to wide format */ + MultiByteToWideChar(CP_ACP, 0, file, strlen(file)+1, wfile, wclen); + if(!GdipCreateBitmapFromFile(wfile, &image)) + return image; + } + } + return NULL; +} + +/* Try to load the appropriate image and return the HBITMAP handle */ +HBITMAP _dw_load_bitmap(char *filename, unsigned long *depth) +{ + void *bitmap = _dw_load_gpbitmap(filename); + if(bitmap) + { + HBITMAP hbm = NULL; + + if(!GdipCreateHBITMAPFromBitmap(bitmap, &hbm, 0)) + { + if(depth) + { + INT pf; + + /* Default to 0 */ + *depth = 0; + + /* Query the pixel format so we can determine the depth */ + if(!GdipGetImagePixelFormat(bitmap, &pf)) + { + switch(pf) + { + case PixelFormat1bppIndexed: + *depth = 1; + break; + case PixelFormat4bppIndexed: + *depth = 4; + break; + case PixelFormat8bppIndexed: + *depth = 8; + break; + case PixelFormat16bppGrayScale: + case PixelFormat16bppRGB555: + case PixelFormat16bppRGB565: + case PixelFormat16bppARGB1555: + *depth = 16; + break; + case PixelFormat24bppRGB: + *depth = 24; + break; + case PixelFormat32bppRGB: + case PixelFormat32bppARGB: + case PixelFormat32bppPARGB: + case PixelFormat32bppCMYK: + *depth = 32; + break; + case PixelFormat48bppRGB: + *depth = 48; + break; + case PixelFormat64bppARGB: + case PixelFormat64bppPARGB: + *depth = 64; + break; + } + } + } + } + GdipDisposeImage(bitmap); + return hbm; + } + return NULL; +} + +/* Try to load the appropriate image and return the HICON handle */ +HICON _dw_load_icon(char *filename) +{ + void *bitmap = _dw_load_gpbitmap(filename); + if(bitmap) + { + HICON hicon = NULL; + + GdipCreateHICONFromBitmap(bitmap, &hicon); + GdipDisposeImage(bitmap); + return hicon; + } + return NULL; +} +#endif + +/* This function adds a signal handler callback into the linked list. + */ +void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data) +{ + SignalHandler *new = malloc(sizeof(SignalHandler)); + + new->message = message; + new->window = window; + new->id = id; + new->signalfunction = signalfunction; + new->data = data; + new->next = NULL; + + if (!Root) + { + Root = new; + } + else + { + SignalHandler *prev = NULL, *tmp = Root; + while(tmp) + { + if(tmp->message == message && + tmp->window == window && + tmp->id == id && + tmp->signalfunction == signalfunction) + { + tmp->data = data; + free(new); + return; + } + prev = tmp; + tmp = tmp->next; + } + if(prev) + prev->next = new; + else + Root = new; + } +} + +/* Finds the message number for a given signal name */ +ULONG _findsigmessage(char *signame) +{ + int z; + + for(z=0;z<SIGNALMAX;z++) + { + if(stricmp(signame, SignalTranslate[z].name) == 0) + return SignalTranslate[z].message; + } + return 0L; +} + +/* This function removes and handlers on windows and frees + * the user memory allocated to it. + */ +BOOL CALLBACK _free_window_memory(HWND handle, LPARAM lParam) +{ + ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + HFONT oldfont = (HFONT)SendMessage(handle, WM_GETFONT, 0, 0); + HICON oldicon = (HICON)SendMessage(handle, WM_GETICON, 0, 0); + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + /* Don't try to free memory from an OLE embedded IE */ + if(strncmp(tmpbuf, "Internet Explorer_Server", 25) == 0) + return TRUE; + + /* Delete font, icon and bitmap GDI objects in use */ + if(oldfont) + DeleteObject(oldfont); + if(oldicon) + DeleteObject(oldicon); + + if(strnicmp(tmpbuf, STATICCLASSNAME, strlen(STATICCLASSNAME)+1)==0) + { + HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, STM_GETIMAGE, IMAGE_BITMAP, 0); + + if(oldbitmap) + DeleteObject(oldbitmap); + } + if(strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0) + { + HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, BM_GETIMAGE, IMAGE_BITMAP, 0); + + if(oldbitmap) + DeleteObject(oldbitmap); + } + else if(strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1)==0) + { + Box *box = (Box *)thiscinfo; + + if(box && box->count && box->items) + free(box->items); + } + else if(strnicmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0) + { + void *data = dw_window_get_data(handle, "_dw_percent"); + + if(data) + free(data); + } + else if(strnicmp(tmpbuf, WC_TREEVIEW, strlen(WC_TREEVIEW)+1)==0) + { + dw_tree_clear(handle); + } + else if(strnicmp(tmpbuf, WC_TABCONTROL, strlen(WC_TABCONTROL)+1)==0) /* Notebook */ + { + NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); + + if(array) + { + int z; + + for(z=0;z<256;z++) + { + if(array[z]) + { + _free_window_memory(array[z]->hwnd, 0); + EnumChildWindows(array[z]->hwnd, _free_window_memory, 0); + DestroyWindow(array[z]->hwnd); + free(array[z]); + } + } + free(array); + } + } + else if(strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0) + { + /* for spinbuttons, we need to get the spinbutton's "buddy", the text window associated and destroy it */ + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + + if(cinfo && cinfo->buddy) + DestroyWindow( cinfo->buddy ); + } + + dw_signal_disconnect_by_window(handle); + + if(thiscinfo) + { + SubclassWindow(handle, thiscinfo->pOldProc); + + /* Delete the brush so as not to leak GDI objects */ + if(thiscinfo->hbrush) + DeleteObject(thiscinfo->hbrush); + + /* Free user data linked list memory */ + if(thiscinfo->root) + dw_window_set_data(handle, NULL, NULL); + + SetWindowLongPtr(handle, GWLP_USERDATA, 0); + free(thiscinfo); + } + return TRUE; +} + +void _free_menu_data(HMENU menu) +{ + int i, count = GetMenuItemCount(menu); + + for(i=0;i<count;i++) + { + MENUITEMINFO mii; + + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_SUBMENU | MIIM_ID; + + if ( GetMenuItemInfo( menu, i, TRUE, &mii ) ) + { + /* Free the data associated with the ID */ + if(mii.wID >= 30000) + { + char buffer[31] = {0}; + + _snprintf(buffer, 30, "_dw_id%ld", mii.wID); + dw_window_set_data( DW_HWND_OBJECT, buffer, NULL ); + _snprintf(buffer, 30, "_dw_checkable%ld", mii.wID); + dw_window_set_data( DW_HWND_OBJECT, buffer, NULL ); + _snprintf(buffer, 30, "_dw_ischecked%ld", mii.wID); + dw_window_set_data( DW_HWND_OBJECT, buffer, NULL ); + _snprintf(buffer, 30, "_dw_isdisabled%ld", mii.wID); + dw_window_set_data( DW_HWND_OBJECT, buffer, NULL ); + } + + /* Check any submenus */ + if( mii.hSubMenu ) + _free_menu_data(mii.hSubMenu); + } + } + dw_signal_disconnect_by_name((HWND)menu, DW_SIGNAL_CLICKED); +} + +/* Convert to our internal color scheme */ +ULONG _internal_color(ULONG color) +{ + if(color == DW_CLR_DEFAULT) + return DW_RGB_TRANSPARENT; + if(color < 18) + return DW_RGB(_red[color], _green[color], _blue[color]); + return color; +} + +/* This function returns 1 if the window (widget) handle + * passed to it is a valid window that can gain input focus. + */ +int _validate_focus(HWND handle) +{ + char tmpbuf[100]; + + if(!handle) + return 0; + + if(!IsWindowEnabled(handle)) + return 0; + + GetClassName(handle, tmpbuf, 99); + + /* These are the window classes which can + * obtain input focus. + */ + if(strnicmp(tmpbuf, EDITCLASSNAME, strlen(EDITCLASSNAME)+1)==0 || /* Entryfield */ + strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0 || /* Button */ + strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0 || /* Combobox */ + strnicmp(tmpbuf, LISTBOXCLASSNAME, strlen(LISTBOXCLASSNAME)+1)==0 || /* List box */ + strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0 || /* Spinbutton */ + strnicmp(tmpbuf, TRACKBAR_CLASS, strlen(TRACKBAR_CLASS)+1)==0 || /* Slider */ + strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW)+1)== 0 || /* Container */ + strnicmp(tmpbuf, WC_TREEVIEW, strlen(WC_TREEVIEW)+1)== 0) /* Tree */ + return 1; + return 0; +} + +HWND _normalize_handle(HWND handle) +{ + char tmpbuf[100] = ""; + + GetClassName(handle, tmpbuf, 99); + if(strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS))==0) /* Spinner */ + { + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + + if(cinfo && cinfo->buddy) + return cinfo->buddy; + } + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME))==0) /* Combobox */ + { + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + + if(cinfo && cinfo->buddy) + return cinfo->buddy; + } + return handle; +} + +int _focus_check_box(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=box->count-1;z>-1;z--) + { + 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)) + 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 + { + char tmpbuf[100] = ""; + + GetClassName(box->items[z].hwnd, tmpbuf, 99); + + 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 *)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"); + + if(mybox) + { + Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA); + + if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem)) + return 1; + } + } + else if(strnicmp(tmpbuf, WC_TABCONTROL, strlen(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(notebox, handle, start == 3 ? 3 : 0, defaultitem)) + return 1; + } + } + } + else if(strnicmp(tmpbuf, ScrollClassName, strlen(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(scrollbox, handle, start == 3 ? 3 : 0, 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)) + 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 + { + char tmpbuf[100] = ""; + + GetClassName(box->items[z].hwnd, tmpbuf, 99); + + 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 *)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(strnicmp(tmpbuf, WC_TABCONTROL, strlen(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(strnicmp(tmpbuf, ScrollClassName, strlen(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; +} + +/* This function finds the first widget in the + * layout and moves the current focus to it. + */ +void _initial_focus(HWND handle) +{ + Box *thisbox; + char tmpbuf[100]; + + if(!handle) + return; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, ClassName, strlen(ClassName))!=0) + return; + + + if(handle) + thisbox = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA); + + if(thisbox) + { + _focus_check_box(thisbox, handle, 3, thisbox->defaultitem); + } +} + +HWND _toplevel_window(HWND handle) +{ + HWND box, lastbox = GetParent(handle); + + /* Find the toplevel window */ + while((box = GetParent(lastbox))) + { + lastbox = box; + } + if(lastbox) + return lastbox; + return handle; +} + +/* This function finds the current widget in the + * layout and moves the current focus to the next item. + */ +void _shift_focus(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(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); + } +} + +/* This function calculates how much space the widgets and boxes require + * and does expansion as necessary. + */ +int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy, + int pass, int *usedpadx, int *usedpady) +{ + int z, currentx = 0, currenty = 0; + int uymax = 0, uxmax = 0; + int upymax = 0, upxmax = 0; + /* Used for the SIZEEXPAND */ + int nux = *usedx, nuy = *usedy; + int nupx = *usedpadx, nupy = *usedpady; + + (*usedx) += (thisbox->pad * 2); + (*usedy) += (thisbox->pad * 2); + + if(thisbox->grouphwnd) + { + char *text = dw_window_get_text(thisbox->grouphwnd); + + thisbox->grouppady = 0; + + if(text) + { + dw_font_text_extents_get(thisbox->grouphwnd, 0, text, NULL, &thisbox->grouppady); + dw_free(text); + } + + if(thisbox->grouppady) + thisbox->grouppady += 3; + else + thisbox->grouppady = 6; + + thisbox->grouppadx = 6; + + (*usedx) += thisbox->grouppadx; + (*usedpadx) += thisbox->grouppadx; + (*usedy) += thisbox->grouppady; + (*usedpady) += thisbox->grouppady; + } + + for(z=0;z<thisbox->count;z++) + { + if(thisbox->items[z].type == TYPEBOX) + { + int initialx, initialy; + Box *tmp = (Box *)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA); + + initialx = x - (*usedx); + initialy = y - (*usedy); + + if(tmp) + { + int newx, newy; + int nux = *usedx, nuy = *usedy; + int upx = *usedpadx + (tmp->pad*2), upy = *usedpady + (tmp->pad*2); + + /* On the second pass we know how big the box needs to be and how + * much space we have, so we can calculate a ratio for the new box. + */ + if(pass == 2) + { + int deep = *depth + 1; + + _resize_box(tmp, &deep, x, y, &nux, &nuy, 1, &upx, &upy); + + tmp->upx = upx - *usedpadx; + tmp->upy = upy - *usedpady; + + newx = x - nux; + newy = y - nuy; + + tmp->width = thisbox->items[z].width = initialx - newx; + tmp->height = thisbox->items[z].height = initialy - newy; + + tmp->parentxratio = thisbox->xratio; + tmp->parentyratio = thisbox->yratio; + + tmp->parentpad = tmp->pad; + + /* Just in case */ + tmp->xratio = thisbox->xratio; + tmp->yratio = thisbox->yratio; + + if(thisbox->type == DW_VERT) + { + int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppady; + + if((thisbox->items[z].width - tmppad)!=0) + tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmppad))/((float)(thisbox->items[z].width-tmppad)); + } + else + { + if((thisbox->items[z].width-tmp->upx)!=0) + tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx)); + } + if(thisbox->type == DW_HORZ) + { + int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppadx; + + if((thisbox->items[z].height-tmppad)!=0) + tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmppad))/((float)(thisbox->items[z].height-tmppad)); + } + else + { + if((thisbox->items[z].height-tmp->upy)!=0) + tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy)); + } + + nux = *usedx; nuy = *usedy; + upx = *usedpadx + (tmp->pad*2); upy = *usedpady + (tmp->pad*2); + } + + (*depth)++; + + _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy); + + (*depth)--; + + newx = x - nux; + newy = y - nuy; + + tmp->minwidth = thisbox->items[z].width = initialx - newx; + tmp->minheight = thisbox->items[z].height = initialy - newy; + } + } + + if(pass > 1 && *depth > 0) + { + if(thisbox->type == DW_VERT) + { + int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppadx; + + if((thisbox->minwidth-tmppad) == 0) + thisbox->items[z].xratio = 1.0; + else + thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-tmppad))/((float)(thisbox->minwidth-tmppad)); + } + else + { + if(thisbox->minwidth-thisbox->upx == 0) + thisbox->items[z].xratio = 1.0; + else + thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx)); + } + + if(thisbox->type == DW_HORZ) + { + int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppady; + + if((thisbox->minheight-tmppad) == 0) + thisbox->items[z].yratio = 1.0; + else + thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-tmppad))/((float)(thisbox->minheight-tmppad)); + } + else + { + if(thisbox->minheight-thisbox->upy == 0) + thisbox->items[z].yratio = 1.0; + else + thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy)); + } + + if(thisbox->items[z].type == TYPEBOX) + { + Box *tmp = (Box *)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA); + + if(tmp) + { + tmp->parentxratio = thisbox->items[z].xratio; + tmp->parentyratio = thisbox->items[z].yratio; + } + } + } + else + { + thisbox->items[z].xratio = thisbox->xratio; + thisbox->items[z].yratio = thisbox->yratio; + } + + if(thisbox->type == DW_VERT) + { + int itemwidth = (thisbox->items[z].pad*2) + thisbox->items[z].width; + + if(itemwidth > uxmax) + uxmax = itemwidth; + if(thisbox->items[z].hsize != SIZEEXPAND) + { + if(itemwidth > upxmax) + upxmax = itemwidth; + } + else + { + if(thisbox->items[z].pad*2 > upxmax) + upxmax = thisbox->items[z].pad*2; + } + } + else + { + if(thisbox->items[z].width == -1) + { + /* figure out how much space this item requires */ + /* thisbox->items[z].width = */ + } + else + { + (*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2); + if(thisbox->items[z].hsize != SIZEEXPAND) + (*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width; + else + (*usedpadx) += thisbox->items[z].pad*2; + } + } + if(thisbox->type == DW_HORZ) + { + int itemheight = (thisbox->items[z].pad*2) + thisbox->items[z].height; + + if(itemheight > uymax) + uymax = itemheight; + if(thisbox->items[z].vsize != SIZEEXPAND) + { + if(itemheight > upymax) + upymax = itemheight; + } + else + { + if(thisbox->items[z].pad*2 > upymax) + upymax = thisbox->items[z].pad*2; + } + } + else + { + if(thisbox->items[z].height == -1) + { + /* figure out how much space this item requires */ + /* thisbox->items[z].height = */ + } + else + { + (*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2); + if(thisbox->items[z].vsize != SIZEEXPAND) + (*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height; + else + (*usedpady) += thisbox->items[z].pad*2; + } + } + } + + (*usedx) += uxmax; + (*usedy) += uymax; + (*usedpadx) += upxmax; + (*usedpady) += upymax; + + currentx += thisbox->pad; + currenty += thisbox->pad; + + if(thisbox->grouphwnd) + { + currentx += 3; + currenty += thisbox->grouppady - 3; + } + + /* The second pass is for expansion and actual placement. */ + if(pass > 1) + { + /* Any SIZEEXPAND items should be set to uxmax/uymax */ + for(z=0;z<thisbox->count;z++) + { + if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == DW_VERT) + thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2); + if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == DW_HORZ) + thisbox->items[z].height = uymax-(thisbox->items[z].pad*2); + /* Run this code segment again to finalize the sized after setting uxmax/uymax values. */ + if(thisbox->items[z].type == TYPEBOX) + { + Box *tmp = (Box *)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA); + + if(tmp) + { + if(*depth > 0) + { + float calcval; + + if(thisbox->type == DW_VERT) + { + calcval = (float)(tmp->minwidth-((thisbox->items[z].pad*2)+(thisbox->pad*2))); + if(calcval == 0.0) + tmp->xratio = thisbox->xratio; + else + tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval; + tmp->width = thisbox->items[z].width; + } + if(thisbox->type == DW_HORZ) + { + calcval = (float)(tmp->minheight-((thisbox->items[z].pad*2)+(thisbox->pad*2))); + if(calcval == 0.0) + tmp->yratio = thisbox->yratio; + else + tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval; + tmp->height = thisbox->items[z].height; + } + } + + (*depth)++; + + _resize_box(tmp, depth, x, y, &nux, &nuy, 3, &nupx, &nupy); + + (*depth)--; + + } + } + } + + for(z=0;z<(thisbox->count);z++) + { + int height = thisbox->items[z].height; + int width = thisbox->items[z].width; + int pad = thisbox->items[z].pad; + HWND handle = thisbox->items[z].hwnd; + int vectorx, vectory; + + /* When upxmax != pad*2 then ratios are incorrect. */ + vectorx = (int)((width*thisbox->items[z].xratio)-width); + vectory = (int)((height*thisbox->items[z].yratio)-height); + + if(width > 0 && height > 0) + { + char tmpbuf[100]; + /* This is a hack to fix rounding of the sizing */ + if(*depth == 0) + { + vectorx++; + vectory++; + } + + /* If this item isn't going to expand... reset the vectors to 0 */ + if(thisbox->items[z].vsize != SIZEEXPAND) + vectory = 0; + if(thisbox->items[z].hsize != SIZEEXPAND) + vectorx = 0; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + { + /* Handle special case Combobox */ + MoveWindow(handle, currentx + pad, currenty + pad, + width + vectorx, (height + vectory) + 400, FALSE); + } + else if(strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0) + { + /* Handle special case Spinbutton */ + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + + MoveWindow(handle, currentx + pad + ((width + vectorx) - 20), currenty + pad, + 20, height + vectory, FALSE); + + if(cinfo) + { + MoveWindow(cinfo->buddy, currentx + pad, currenty + pad, + (width + vectorx) - 20, height + vectory, FALSE); + } + } + else if(strncmp(tmpbuf, ScrollClassName, strlen(ScrollClassName)+1)==0) + { + /* Handle special case of scrollbox */ + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + int cx = width + vectorx; + int cy = height + vectory; + int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0; + Box *thisbox = (Box *)GetWindowLongPtr(cinfo->combo, GWLP_USERDATA); + SCROLLINFO hsi, vsi; + RECT rect; + + vsi.cbSize = hsi.cbSize = sizeof(SCROLLINFO); + vsi.fMask = hsi.fMask = SIF_POS; + + /* Save the current scroll positions */ + GetScrollInfo(handle, SB_HORZ, &hsi); + GetScrollInfo(handle, SB_VERT, &vsi); + + /* Position the scrollbox */ + MoveWindow(handle, currentx + pad, currenty + pad, cx, cy, FALSE); + + GetClientRect(handle, &rect); + cx = rect.right; + cy = rect.bottom; + + + /* Get the required space for the box */ + _resize_box(thisbox, &depth, cx, cy, &usedx, &usedy, 1, &usedpadx, &usedpady); + + if(cx < usedx) + { + cx = usedx; + } + if(cy < usedy) + { + cy = usedy; + } + + /* Position the scrolled box */ + vsi.fMask = hsi.fMask = SIF_POS | SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL; + vsi.nMin = hsi.nMin = vsi.nMax = hsi.nMax = 0; + if(rect.bottom < usedy) + { + vsi.nMax = usedy; + vsi.nPage = rect.bottom; + if(vsi.nPos > vsi.nMax) + { + vsi.nPos = vsi.nMax; + } + } + if(rect.right < usedx) + { + hsi.nMax = usedx; + hsi.nPage = rect.right; + if(hsi.nPos > hsi.nMax) + { + hsi.nPos = hsi.nMax; + } + } + MoveWindow(cinfo->combo, -hsi.nPos, -vsi.nPos, cx, cy, FALSE); + SetScrollInfo(handle, SB_HORZ, &hsi, TRUE); + SetScrollInfo(handle, SB_VERT, &vsi, TRUE); + + /* Layout the content of the scrollbox */ + _do_resize(thisbox, cx, cy); + } + else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0) + { + /* 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 cx = width + vectorx; + int cy = height + vectory; + + MoveWindow(handle, currentx + pad, currenty + pad, + cx, cy, FALSE); + + if(cx > 0 && cy > 0 && percent) + _handle_splitbar_resize(handle, *percent, type, cx, cy); + } + else if(strnicmp(tmpbuf, STATICCLASSNAME, strlen(STATICCLASSNAME)+1)==0) + { + /* Handle special case Vertically Center static text */ + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + + if(cinfo && cinfo->vcenter) + { + /* We are centered so calculate a new position */ + char tmpbuf[1024]; + int textheight, diff, total = height + vectory; + + GetWindowText(handle, tmpbuf, 1023); + + /* Figure out how big the text is */ + dw_font_text_extents_get(handle, 0, tmpbuf, 0, &textheight); + + diff = (total - textheight) / 2; + + MoveWindow(handle, currentx + pad, currenty + pad + diff, + width + vectorx, height + vectory - diff, FALSE); + } + else + { + MoveWindow(handle, currentx + pad, currenty + pad, + width + vectorx, height + vectory, FALSE); + } + } + else + { + /* Everything else */ + MoveWindow(handle, currentx + pad, currenty + pad, + width + vectorx, height + vectory, FALSE); + if(thisbox->items[z].type == TYPEBOX) + { + Box *boxinfo = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA); + + if(boxinfo && boxinfo->grouphwnd) + { + MoveWindow(boxinfo->grouphwnd, 0, 0, + width + vectorx, height + vectory, FALSE); + } + + } + } + + /* Notebook dialog requires additional processing */ + if(strncmp(tmpbuf, WC_TABCONTROL, strlen(WC_TABCONTROL))==0) + { + RECT rect; + NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); + int pageid = TabCtrl_GetCurSel(handle); + + if(pageid > -1 && array && array[pageid]) + { + GetClientRect(handle,&rect); + TabCtrl_AdjustRect(handle,FALSE,&rect); + MoveWindow(array[pageid]->hwnd, rect.left, rect.top, + rect.right - rect.left, rect.bottom-rect.top, FALSE); + } + } + + if(thisbox->type == DW_HORZ) + currentx += width + vectorx + (pad * 2); + if(thisbox->type == DW_VERT) + currenty += height + vectory + (pad * 2); + } + } + } + return 0; +} + +void _do_resize(Box *thisbox, int x, int y) +{ + if(x != 0 && y != 0) + { + if(thisbox) + { + int usedx = 0, usedy = 0, depth = 0, usedpadx = 0, usedpady = 0; + + _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady); + + if(usedx-usedpadx == 0 || usedy-usedpady == 0) + return; + + thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx)); + thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady)); + + usedpadx = usedpady = usedx = usedy = depth = 0; + + _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady); + } + } +} + +int _HandleScroller(HWND handle, int bar, int pos, int which) +{ + SCROLLINFO si; + + ZeroMemory( &si, sizeof(si) ); + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_ALL; + + SendMessage(handle, SBM_GETSCROLLINFO, 0, (LPARAM)&si); + + switch(which) + { + case SB_THUMBTRACK: + return pos; + /*case SB_PAGEUP:*/ + case SB_PAGELEFT: + pos = si.nPos - si.nPage; + if(pos < si.nMin) + pos = si.nMin; + return pos; + /*case SB_PAGEDOWN:*/ + case SB_PAGERIGHT: + pos = si.nPos + si.nPage; + if(pos > (si.nMax - si.nPage) + 1) + pos = (si.nMax - si.nPage) + 1; + return pos; + /*case SB_LINEUP:*/ + case SB_LINELEFT: + pos = si.nPos - 1; + if(pos < si.nMin) + pos = si.nMin; + return pos; + /*case SB_LINEDOWN:*/ + case SB_LINERIGHT: + pos = si.nPos + 1; + if(pos > (si.nMax - si.nPage) + 1) + pos = (si.nMax - si.nPage) + 1; + return pos; + } + return -1; +} + +HMENU _get_owner(HMENU menu) +{ + MENUINFO mi; + + mi.cbSize = sizeof(MENUINFO); + mi.fMask = MIM_MENUDATA; + + if ( GetMenuInfo( menu, &mi ) ) + return (HMENU)mi.dwMenuData; + return (HMENU)0; +} + +/* Find the desktop window handle */ +HMENU _menu_owner(HMENU handle) +{ + HMENU menuowner = 0, lastowner = _get_owner(handle); + + /* Find the toplevel menu */ + while((menuowner = _get_owner(lastowner)) != 0) + { + if(menuowner == (HMENU)1) + return lastowner; + lastowner = menuowner; + } + return (HMENU)0; +} + +/* + * Determine if this is a checkable menu. If it is get the current state + * and toggle it. Windows doesn't do this automatically :-( + */ +static void _dw_toggle_checkable_menu_item( HWND window, int id ) +{ + char buffer[40]; + int checkable; + sprintf( buffer, "_dw_checkable%ld", id ); + checkable = (int)dw_window_get_data(DW_HWND_OBJECT, buffer); + if ( checkable ) + { + int is_checked; + sprintf( buffer, "_dw_ischecked%ld", id ); + is_checked = (int)dw_window_get_data(DW_HWND_OBJECT, buffer); + is_checked = (is_checked) ? 0 : 1; + dw_menu_item_set_check( window, id, is_checked ); + } +} + +/* The main window procedure for Dynamic Windows, all the resizing code is done here. */ +BOOL CALLBACK _wndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ + int result = -1, taskbar = FALSE; + static int command_active = 0; + SignalHandler *tmp = Root; + void (*windowfunc)(PVOID); + ULONG origmsg = msg; + + /* Deal with translating some messages */ + if (msg == WM_USER+2) + { + taskbar = TRUE; + origmsg = msg = (UINT)mp2; /* no else here */ + } + if (msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) + msg = WM_LBUTTONDOWN; + else if (msg == WM_RBUTTONUP || msg == WM_MBUTTONUP) + msg = WM_LBUTTONUP; + else if (msg == WM_HSCROLL) + msg = WM_VSCROLL; + else if (msg == WM_KEYDOWN) /* && mp1 >= VK_F1 && mp1 <= VK_F24) allow ALL special keys */ + msg = WM_CHAR; + + if (result == -1) + { + /* Avoid infinite recursion */ + command_active = 1; + + /* Find any callbacks for this function */ + while (tmp) + { + if (tmp->message == msg || msg == WM_COMMAND || msg == WM_NOTIFY || tmp->message == WM_USER+1) + { + switch (msg) + { + case WM_TIMER: + { + if (!hWnd) + { + int (*timerfunc)(void *) = tmp->signalfunction; + if (tmp->id == (int)mp1) + { + if (!timerfunc(tmp->data)) + { + dw_timer_disconnect(tmp->id); + } + tmp = NULL; + } + } + result = 0; + } + break; + case WM_SETFOCUS: + { + int (*setfocusfunc)(HWND, void *) = (int (*)(HWND, void *))tmp->signalfunction; + + if(hWnd == tmp->window) + { + result = setfocusfunc(tmp->window, tmp->data); + tmp = NULL; + } + } + break; + case WM_SIZE: + { + int (*sizefunc)(HWND, int, int, void *) = tmp->signalfunction; + if(hWnd == tmp->window) + { + result = sizefunc(tmp->window, LOWORD(mp2), HIWORD(mp2), tmp->data); + tmp = NULL; + } + } + break; + case WM_LBUTTONDOWN: + { + int (*buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; + + if(hWnd == tmp->window) + { + int button=0; + + switch(origmsg) + { + case WM_LBUTTONDOWN: + button = 1; + break; + case WM_RBUTTONDOWN: + button = 2; + break; + case WM_MBUTTONDOWN: + button = 3; + break; + } + if(taskbar) + { + POINT ptl; + GetCursorPos(&ptl); + result = buttonfunc(tmp->window, ptl.x, ptl.y, button, tmp->data); + } + else + { + POINTS pts = MAKEPOINTS(mp2); + result = buttonfunc(tmp->window, pts.x, pts.y, button, tmp->data); + } + tmp = NULL; + } + } + break; + case WM_LBUTTONUP: + { + int (*buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; + + if(hWnd == tmp->window) + { + int button=0; + + switch(origmsg) + { + case WM_LBUTTONUP: + button = 1; + break; + case WM_RBUTTONUP: + button = 2; + break; + case WM_MBUTTONUP: + button = 3; + break; + } + if(taskbar) + { + POINT ptl; + GetCursorPos(&ptl); + result = buttonfunc(tmp->window, ptl.x, ptl.y, button, tmp->data); + } + else + { + POINTS pts = MAKEPOINTS(mp2); + result = buttonfunc(tmp->window, pts.x, pts.y, button, tmp->data); + } + tmp = NULL; + } + } + break; + case WM_MOUSEMOVE: + { + POINTS pts = MAKEPOINTS(mp2); + int (*motionfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction; + + if(hWnd == tmp->window) + { + int keys = 0; + + if (mp1 & MK_LBUTTON) + keys = DW_BUTTON1_MASK; + if (mp1 & MK_RBUTTON) + keys |= DW_BUTTON2_MASK; + if (mp1 & MK_MBUTTON) + keys |= DW_BUTTON3_MASK; + + result = motionfunc(tmp->window, pts.x, pts.y, keys, tmp->data); + tmp = NULL; + } + } + break; + case WM_CHAR: + { + int (*keypressfunc)(HWND, char, int, int, void *) = tmp->signalfunction; + + if(hWnd == tmp->window || _toplevel_window(hWnd) == tmp->window) + { + int special = 0; + char ch = 0; + + if(GetAsyncKeyState(VK_SHIFT) & 0x8000) + special |= KC_SHIFT; + if(GetAsyncKeyState(VK_CONTROL) & 0x8000) + special |= KC_CTRL; + if(mp2 & (1 << 29)) + special |= KC_ALT; + + if(origmsg == WM_CHAR && mp1 < 128) + ch = (char)mp1; + + result = keypressfunc(tmp->window, ch, mp1, special, tmp->data); + tmp = NULL; + } + } + break; + case WM_CLOSE: + { + int (*closefunc)(HWND, void *) = tmp->signalfunction; + + if(hWnd == tmp->window) + { + result = closefunc(tmp->window, tmp->data); + tmp = NULL; + } + } + break; + case WM_PAINT: + { + PAINTSTRUCT ps; + DWExpose exp; + int (*exposefunc)(HWND, DWExpose *, void *) = tmp->signalfunction; + + if ( hWnd == tmp->window ) + { + BeginPaint(hWnd, &ps); + exp.x = ps.rcPaint.left; + exp.y = ps.rcPaint.top; + exp.width = ps.rcPaint.right - ps.rcPaint.left; + exp.height = ps.rcPaint.bottom - ps.rcPaint.top; + result = exposefunc(hWnd, &exp, tmp->data); + EndPaint(hWnd, &ps); + } + } + break; + case WM_NOTIFY: + { + if(tmp->message == TVN_SELCHANGED || + tmp->message == NM_RCLICK || + tmp->message == TVN_ITEMEXPANDED) + { + NMTREEVIEW FAR *tem=(NMTREEVIEW FAR *)mp2; + NMLISTVIEW FAR *lem=(NMLISTVIEW FAR *)mp2; + char tmpbuf[100]; + + GetClassName(tem->hdr.hwndFrom, tmpbuf, 99); + + if(strnicmp(tmpbuf, WC_TREEVIEW, strlen(WC_TREEVIEW))==0) + { + if(tem->hdr.code == TVN_SELCHANGED && tmp->message == TVN_SELCHANGED) + { + if(tmp->window == tem->hdr.hwndFrom && !dw_window_get_data(tmp->window, "_dw_select_item")) + { + int (*treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = tmp->signalfunction; + TVITEM tvi; + void **ptrs; + + tvi.mask = TVIF_HANDLE | TVIF_PARAM; + tvi.hItem = tem->itemNew.hItem; + + 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]); + + tmp = NULL; + } + } + else if(tem->hdr.code == TVN_ITEMEXPANDED && tmp->message == TVN_ITEMEXPANDED) + { + if(tmp->window == tem->hdr.hwndFrom && tem->action == TVE_EXPAND) + { + int (*treeexpandfunc)(HWND, HTREEITEM, void *) = tmp->signalfunction; + + result = treeexpandfunc(tmp->window, tem->itemNew.hItem, tmp->data); + tmp = NULL; + } + } + else if(tem->hdr.code == NM_RCLICK && tmp->message == NM_RCLICK) + { + if(tmp->window == tem->hdr.hwndFrom) + { + int (*containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction; + HTREEITEM hti, last; + TVITEM tvi; + TVHITTESTINFO thi; + void **ptrs = NULL; + LONG x, y; + + dw_pointer_query_pos(&x, &y); + + thi.pt.x = x; + thi.pt.y = y; + + MapWindowPoints(HWND_DESKTOP, tmp->window, &thi.pt, 1); + + last = TreeView_GetSelection(tmp->window); + hti = TreeView_HitTest(tmp->window, &thi); + + if(hti) + { + tvi.mask = TVIF_HANDLE | TVIF_PARAM; + tvi.hItem = hti; + + TreeView_GetItem(tmp->window, &tvi); + TreeView_SelectItem(tmp->window, hti); + + ptrs = (void **)tvi.lParam; + } + containercontextfunc(tmp->window, ptrs ? (char *)ptrs[0] : NULL, x, y, tmp->data, ptrs ? ptrs[1] : NULL); + tmp = NULL; + } + } + } + else if(strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW)+1)==0) + { + if((lem->hdr.code == LVN_ITEMCHANGED && (lem->uChanged & LVIF_STATE)) && tmp->message == TVN_SELCHANGED) + { + if(tmp->window == tem->hdr.hwndFrom) + { + LV_ITEM lvi; + int iItem; + + iItem = ListView_GetNextItem(tmp->window, -1, LVNI_SELECTED); + + memset(&lvi, 0, sizeof(LV_ITEM)); + + if(iItem > -1) + { + int (*treeselectfunc)(HWND, HWND, char *, void *, void *) = tmp->signalfunction; + + 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); + tmp = NULL; + } + } + } + } + } + else if(tmp->message == TCN_SELCHANGE) + { + NMHDR FAR *tem=(NMHDR FAR *)mp2; + if(tmp->window == tem->hwndFrom && tem->code == tmp->message) + { + int (*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; + } + } + else if(tmp->message == LVN_COLUMNCLICK) + { + NMLISTVIEW FAR *tem=(NMLISTVIEW FAR *)mp2; + if(tmp->window == tem->hdr.hwndFrom && tem->hdr.code == tmp->message) + { + int (*columnclickfunc)(HWND, int, void *) = tmp->signalfunction; + result = columnclickfunc(tem->hdr.hwndFrom, tem->iSubItem, tmp->data); + tmp = NULL; + } + } + } + break; + case WM_COMMAND: + { + int (*clickfunc)(HWND, void *) = tmp->signalfunction; + HWND command; + ULONG passthru = (ULONG)LOWORD(mp1); + ULONG message = HIWORD(mp1); + + command = (HWND)passthru; + + if (message == LBN_SELCHANGE || message == CBN_SELCHANGE) + { + int (*listboxselectfunc)(HWND, int, void *) = tmp->signalfunction; + + if (tmp->message == LBN_SELCHANGE && tmp->window == (HWND)mp2) + { + result = listboxselectfunc(tmp->window, dw_listbox_selected(tmp->window), tmp->data); + tmp = NULL; + } + } + else if (tmp->id && passthru == tmp->id) + { + HMENU hwndmenu = GetMenu(hWnd), menuowner = _menu_owner((HMENU)tmp->window); + + if (menuowner == hwndmenu || !menuowner) + { + _dw_toggle_checkable_menu_item( tmp->window, tmp->id ); + /* + * Call the user supplied callback + */ + result = clickfunc(tmp->window, 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 ); + result = clickfunc(popup ? popup : tmp->window, tmp->data); + tmp = NULL; + } + } + break; + case WM_HSCROLL: + case WM_VSCROLL: + { + char tmpbuf[100] = ""; + HWND handle = (HWND)mp2; + int (*valuechangefunc)(HWND, int, void *) = tmp->signalfunction; + + if(!GetClassName(handle, tmpbuf, 99)) + { + GetClassName(hWnd, tmpbuf, 99); + } + + if (strnicmp(tmpbuf, TRACKBAR_CLASS, strlen(TRACKBAR_CLASS)+1)==0) + { + + if (handle == tmp->window) + { + int value = (int)SendMessage(handle, TBM_GETPOS, 0, 0); + int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0); + ULONG currentstyle = GetWindowLong(handle, GWL_STYLE); + + if(currentstyle & TBS_VERT) + result = valuechangefunc(tmp->window, max - value, tmp->data); + else + result = valuechangefunc(tmp->window, value, tmp->data); + tmp = NULL; + } + } + else if(strnicmp(tmpbuf, SCROLLBARCLASSNAME, strlen(SCROLLBARCLASSNAME)+1)==0) + { + if(handle == tmp->window) + { + int bar = (origmsg == WM_HSCROLL) ? SB_HORZ : SB_VERT; + int value = _HandleScroller(handle, bar, (int)HIWORD(mp1), (int)LOWORD(mp1)); + + if(value > -1) + { + dw_scrollbar_set_pos(tmp->window, value); + result = valuechangefunc(tmp->window, value, tmp->data); + } + tmp = NULL; + msg = 0; + } + } + } + break; + } + } + if(tmp) + tmp = tmp->next; + } + command_active = 0; + } + + /* Now that any handlers are done... do normal processing */ + switch( msg ) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + + BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + } + break; + case WM_SIZE: + { + static int lastx = -1, lasty = -1; + static HWND lasthwnd = 0; + + if(lastx != LOWORD(mp2) || lasty != HIWORD(mp2) || lasthwnd != hWnd) + { + Box *mybox = (Box *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + if(mybox && mybox->count) + { + lastx = LOWORD(mp2); + lasty = HIWORD(mp2); + lasthwnd = hWnd; + + ShowWindow(mybox->items[0].hwnd, SW_HIDE); + _do_resize(mybox,LOWORD(mp2),HIWORD(mp2)); + ShowWindow(mybox->items[0].hwnd, SW_SHOW); + return 0; + } + } + } + break; + case WM_USER: + windowfunc = (void *)mp1; + + if(windowfunc) + windowfunc((void *)mp2); + break; + case WM_USER+5: + _free_menu_data((HMENU)mp1); + DestroyMenu((HMENU)mp1); + break; + case WM_NOTIFY: + { + NMHDR FAR *tem=(NMHDR FAR *)mp2; + + if(tem->code == TCN_SELCHANGING) + { + int num=TabCtrl_GetCurSel(tem->hwndFrom); + NotebookPage **array = (NotebookPage **)dw_window_get_data(tem->hwndFrom, "_dw_array"); + + if(num > -1 && array && array[num]) + SetParent(array[num]->hwnd, DW_HWND_OBJECT); + + } + else if(tem->code == TCN_SELCHANGE) + { + int num=TabCtrl_GetCurSel(tem->hwndFrom); + NotebookPage **array = (NotebookPage **)dw_window_get_data(tem->hwndFrom, "_dw_array"); + + if(num > -1 && array && array[num]) + SetParent(array[num]->hwnd, tem->hwndFrom); + + _resize_notebook_page(tem->hwndFrom, num); + } + } + break; + case WM_HSCROLL: + case WM_VSCROLL: + { + HWND handle = (HWND)mp2; + char tmpbuf[100]; + int bar = (origmsg == WM_HSCROLL) ? SB_HORZ : SB_VERT; + + if(dw_window_get_data(handle, "_dw_scrollbar")) + { + int value = _HandleScroller(handle, bar, (int)HIWORD(mp1), (int)LOWORD(mp1)); + + if(value > -1) + dw_scrollbar_set_pos(handle, value); + } + else + { + GetClassName( hWnd, tmpbuf, 99 ); + if ( strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1 ) == 0 ) + { + int value = _HandleScroller(hWnd, bar, (int)HIWORD(mp1), (int)LOWORD(mp1)); + } + } + } + break; + case WM_GETMINMAXINFO: + { + MINMAXINFO *info = (MINMAXINFO *)mp2; + info->ptMinTrackSize.x = 8; + info->ptMinTrackSize.y = 8; + return 0; + } + break; + case WM_DESTROY: + { + HMENU menu = GetMenu(hWnd); + + if(menu) + _free_menu_data(menu); + + /* Free memory before destroying */ + _free_window_memory(hWnd, 0); + EnumChildWindows(hWnd, _free_window_memory, 0); + } + break; + case WM_MOUSEMOVE: + { + HCURSOR cursor; + + if((cursor = (HCURSOR)dw_window_get_data(hWnd, "_dw_cursor")) || + (cursor = (HCURSOR)dw_window_get_data(_toplevel_window(hWnd), "_dw_cursor"))) + { + SetCursor(cursor); + } + } + break; + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORBTN: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORMSGBOX: + case WM_CTLCOLORSCROLLBAR: + case WM_CTLCOLORDLG: + { + ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr((HWND)mp2, GWLP_USERDATA); + if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) + { + /* Handle foreground */ + if(thiscinfo->fore > -1 && thiscinfo->fore < 18) + { + if(thiscinfo->fore != DW_CLR_DEFAULT) + { + SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore], + _green[thiscinfo->fore], + _blue[thiscinfo->fore])); + } + } + else if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR) + { + SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore), + DW_GREEN_VALUE(thiscinfo->fore), + DW_BLUE_VALUE(thiscinfo->fore))); + } + /* Handle background */ + if(thiscinfo->back > -1 && thiscinfo->back < 18) + { + if(thiscinfo->back == DW_CLR_DEFAULT) + { + HBRUSH hbr = GetSysColorBrush(COLOR_3DFACE); + + SelectObject((HDC)mp1, hbr); + return (LONG)hbr; + } + else + { + SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back], + _green[thiscinfo->back], + _blue[thiscinfo->back])); + if(thiscinfo->hbrush) + DeleteObject(thiscinfo->hbrush); + thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back], + _green[thiscinfo->back], + _blue[thiscinfo->back])); + SelectObject((HDC)mp1, thiscinfo->hbrush); + } + return (LONG)thiscinfo->hbrush; + } + else if((thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR) + { + SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back), + DW_GREEN_VALUE(thiscinfo->back), + DW_BLUE_VALUE(thiscinfo->back))); + if(thiscinfo->hbrush) + DeleteObject(thiscinfo->hbrush); + thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back), + DW_GREEN_VALUE(thiscinfo->back), + DW_BLUE_VALUE(thiscinfo->back))); + SelectObject((HDC)mp1, thiscinfo->hbrush); + return (LONG)thiscinfo->hbrush; + } + } + + } + break; + } + if(result != -1) + return result; + else + { + return DefWindowProc(hWnd, msg, mp1, mp2); + } +} + +VOID CALLBACK _TimerProc(HWND hwnd, UINT msg, UINT_PTR idEvent, DWORD dwTime) +{ + _wndproc(hwnd, msg, (WPARAM)idEvent, 0); +} + +BOOL CALLBACK _framewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ + switch( msg ) + { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + SetActiveWindow(hWnd); + SetFocus(hWnd); + break; + case WM_COMMAND: + case WM_NOTIFY: + case WM_MOUSEMOVE: + _wndproc(hWnd, msg, mp1, mp2); + break; +#if 0 + case WM_ERASEBKGND: + { + ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) + return FALSE; + } + break; +#endif + case WM_PAINT: + { + ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) + { + PAINTSTRUCT ps; + HDC hdcPaint = BeginPaint(hWnd, &ps); + int success = FALSE; + + if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) + { + /* Handle foreground */ + if(thiscinfo->fore > -1 && thiscinfo->fore < 18) + { + if(thiscinfo->fore != DW_CLR_DEFAULT) + { + SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore], + _green[thiscinfo->fore], + _blue[thiscinfo->fore])); + } + } + else if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR) + { + SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore), + DW_GREEN_VALUE(thiscinfo->fore), + DW_BLUE_VALUE(thiscinfo->fore))); + } + /* Handle background */ + if(thiscinfo->back > -1 && thiscinfo->back < 18) + { + if(thiscinfo->back != DW_CLR_DEFAULT) + { + SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back], + _green[thiscinfo->back], + _blue[thiscinfo->back])); + if(thiscinfo->hbrush) + DeleteObject(thiscinfo->hbrush); + thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back], + _green[thiscinfo->back], + _blue[thiscinfo->back])); + SelectObject(hdcPaint, thiscinfo->hbrush); + Rectangle(hdcPaint, ps.rcPaint.left - 1, ps.rcPaint.top - 1, ps.rcPaint.right + 1, ps.rcPaint.bottom + 1); + success = TRUE; + } + } + else if((thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR) + { + SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back), + DW_GREEN_VALUE(thiscinfo->back), + DW_BLUE_VALUE(thiscinfo->back))); + if(thiscinfo->hbrush) + DeleteObject(thiscinfo->hbrush); + thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back), + DW_GREEN_VALUE(thiscinfo->back), + DW_BLUE_VALUE(thiscinfo->back))); + SelectObject(hdcPaint, thiscinfo->hbrush); + Rectangle(hdcPaint, ps.rcPaint.left - 1, ps.rcPaint.top - 1, ps.rcPaint.right + 1, ps.rcPaint.bottom + 1); + success = TRUE; + } + } + + EndPaint(hWnd, &ps); + if(success) + return FALSE; + } + + } + break; + } + return DefWindowProc(hWnd, msg, mp1, mp2); +} + +BOOL CALLBACK _rendwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ + BOOL rcode = TRUE; + + switch( msg ) + { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + SetFocus(hWnd); + rcode = _wndproc(hWnd, msg, mp1, mp2); + break; + case WM_MOUSEMOVE: + /* call our standard Windows procedure */ + rcode = _wndproc(hWnd, msg, mp1, mp2); + break; + case WM_USER+2: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + rcode = _wndproc(hWnd, msg, mp1, mp2); + break; + case WM_PAINT: + case WM_SIZE: + case WM_COMMAND: + case WM_CHAR: + case WM_KEYDOWN: + rcode = _wndproc(hWnd, msg, mp1, mp2); + break; + default: + break; + } + /* only call the default Windows process if the user hasn't handled the message themselves */ + if ( rcode != 0 ) + rcode = DefWindowProc(hWnd, msg, mp1, mp2); + return rcode; +} + +BOOL CALLBACK _spinnerwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ + ColorInfo *cinfo; + + cinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + if(msg == WM_MOUSEMOVE) + _wndproc(hWnd, msg, mp1, mp2); + + if(cinfo) + { + switch( msg ) + { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_KEYDOWN: + { + BOOL ret; + + if(!cinfo || !cinfo->pOldProc) + ret = DefWindowProc(hWnd, msg, mp1, mp2); + ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); + + /* Tell the edit control that a buttonpress has + * occured and to update it's window title. + */ + if(cinfo && cinfo->buddy) + SendMessage(cinfo->buddy, WM_USER+10, 0, 0); + + SetTimer(hWnd, 100, 100, (TIMERPROC)NULL); + + return ret; + } + break; + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_KEYUP: + { + BOOL ret; + + if(!cinfo || !cinfo->pOldProc) + ret = DefWindowProc(hWnd, msg, mp1, mp2); + ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); + + /* Tell the edit control that a buttonpress has + * occured and to update it's window title. + */ + if(cinfo && cinfo->buddy) + SendMessage(cinfo->buddy, WM_USER+10, 0, 0); + + if(hWnd) + KillTimer(hWnd, 100); + + return ret; + } + break; + case WM_TIMER: + { + if(mp1 == 100) + { + BOOL ret; + + if(cinfo && cinfo->buddy) + SendMessage(cinfo->buddy, WM_USER+10, 0, 0); + + if(!cinfo || !cinfo->pOldProc) + ret = DefWindowProc(hWnd, msg, mp1, mp2); + ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); + + /* Tell the edit control that a buttonpress has + * occured and to update it's window title. + */ + if(cinfo && cinfo->buddy) + SendMessage(cinfo->buddy, WM_USER+10, 0, 0); + + return ret; + } + } + break; + case WM_USER+10: + { + if(cinfo->buddy) + { + char tempbuf[100] = ""; + long position; + + GetWindowText(cinfo->buddy, tempbuf, 99); + + position = atol(tempbuf); + + SendMessage(hWnd, UDM_SETPOS32, 0, (LPARAM)position); + } + } + break; + } + } + + if(!cinfo || !cinfo->pOldProc) + return DefWindowProc(hWnd, msg, mp1, mp2); + return CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); +} + +void _click_default(HWND handle) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + /* These are the window classes which can + * obtain input focus. + */ + if (strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME))==0) + { + /* Generate click on default item */ + SignalHandler *tmp = Root; + + /* Find any callbacks for this function */ + while (tmp) + { + if (tmp->message == WM_COMMAND) + { + /* Make sure it's the right window, and the right ID */ + if (tmp->window == handle) + { + int (*clickfunc)(HWND, void *) = tmp->signalfunction; + clickfunc(tmp->window, tmp->data); + tmp = NULL; + } + } + if (tmp) + tmp= tmp->next; + } + } + else + SetFocus(handle); +} + +BOOL CALLBACK _colorwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ + ColorInfo *cinfo; + char tmpbuf[100]; + WNDPROC pOldProc = 0; + int ret = -1; + + cinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + GetClassName(hWnd, tmpbuf, 99); + if(strcmp(tmpbuf, FRAMECLASSNAME) == 0) + cinfo = &(((Box *)cinfo)->cinfo); + + if ( msg == WM_MOUSEMOVE || msg == WM_USER+2 ) + ret = _wndproc(hWnd, msg, mp1, mp2); + + if (cinfo) + { + pOldProc = cinfo->pOldProc; + + switch( msg ) + { + case WM_SETFOCUS: + if(cinfo->combo) + ret = _wndproc(cinfo->combo, msg, mp1, mp2); + else + ret = _wndproc(hWnd, msg, mp1, mp2); + break; + case WM_VSCROLL: + case WM_HSCROLL: + ret = _wndproc(hWnd, msg, mp1, mp2); + break; + case WM_KEYDOWN: + case WM_KEYUP: + { + if (hWnd && (mp1 == VK_UP || mp1 == VK_DOWN)) + { + if (!cinfo || !cinfo->pOldProc) + ret = DefWindowProc(hWnd, msg, mp1, mp2); + ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); + + /* Tell the spinner control that a keypress has + * occured and to update it's internal value. + */ + if (cinfo && cinfo->buddy && !cinfo->combo) + PostMessage(hWnd, WM_USER+10, 0, 0); + + if(msg == WM_KEYDOWN) + SetTimer(hWnd, 101, 100, (TIMERPROC)NULL); + else + KillTimer(hWnd, 101); + + return ret; + } + } + break; + case WM_TIMER: + { + if(mp1 == 101) + { + if(!cinfo || !cinfo->pOldProc) + ret = DefWindowProc(hWnd, msg, mp1, mp2); + ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2); + + /* Tell the spinner control that a keypress has + * occured and to update it's internal value. + */ + if(cinfo && cinfo->buddy && !cinfo->combo) + PostMessage(hWnd, WM_USER+10, 0, 0); + + return ret; + } + } + break; + case WM_CHAR: + ret = _wndproc(hWnd, msg, mp1, mp2); + if (ret != TRUE && LOWORD(mp1) == '\t') + { + if (GetAsyncKeyState(VK_SHIFT) & 0x8000) + { + if (cinfo->combo) + _shift_focus_back(cinfo->combo); + else if(cinfo->buddy) + _shift_focus_back(cinfo->buddy); + else + _shift_focus_back(hWnd); + } + else + { + if (cinfo->combo) + _shift_focus(cinfo->combo); + else if(cinfo->buddy) + _shift_focus(cinfo->buddy); + else + _shift_focus(hWnd); + } + return FALSE; + } + else if(LOWORD(mp1) == '\r') + { + + if ( cinfo->clickdefault ) + { + _click_default(cinfo->clickdefault); + } + else + { + /* + * Find the toplevel window for the current window and check if it + * has a default click set + */ + HWND tl = _toplevel_window( hWnd ); + ColorInfo *mycinfo = (ColorInfo *)GetWindowLongPtr( tl, GWLP_USERDATA ); + if ( mycinfo && mycinfo->clickdefault ) + { + _click_default( mycinfo->clickdefault ); + } + } + } + + /* Tell the spinner control that a keypress has + * occured and to update it's internal value. + */ + if (cinfo->buddy && !cinfo->combo) + { + PostMessage(cinfo->buddy, WM_USER+10, 0, 0); + } + break; + case WM_USER+10: + { + if(cinfo->buddy) + { + long val; + + val = (long)SendMessage(cinfo->buddy, UDM_GETPOS32, 0, 0); + + sprintf(tmpbuf, "%ld", val); + SetWindowText(hWnd, tmpbuf); + } + } + break; + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORBTN: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORMSGBOX: + case WM_CTLCOLORSCROLLBAR: + case WM_CTLCOLORDLG: + { + ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr((HWND)mp2, GWLP_USERDATA); + if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1) + { + /* Handle foreground */ + if(thiscinfo->fore > -1 && thiscinfo->fore < 18) + { + if(thiscinfo->fore != DW_CLR_DEFAULT) + { + SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore], + _green[thiscinfo->fore], + _blue[thiscinfo->fore])); + } + } + else if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR) + { + SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore), + DW_GREEN_VALUE(thiscinfo->fore), + DW_BLUE_VALUE(thiscinfo->fore))); + } + /* Handle background */ + if(thiscinfo->back > -1 && thiscinfo->back < 18) + { + if(thiscinfo->back == DW_CLR_DEFAULT) + { + HBRUSH hbr = GetSysColorBrush(COLOR_3DFACE); + + SetBkColor((HDC)mp1, GetSysColor(COLOR_3DFACE)); + + + SelectObject((HDC)mp1, hbr); + return (LONG)hbr; + } + else + { + SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back], + _green[thiscinfo->back], + _blue[thiscinfo->back])); + if(thiscinfo->hbrush) + DeleteObject(thiscinfo->hbrush); + thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back], + _green[thiscinfo->back], + _blue[thiscinfo->back])); + SelectObject((HDC)mp1, thiscinfo->hbrush); + } + return (LONG)thiscinfo->hbrush; + } + else if((thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR) + { + SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back), + DW_GREEN_VALUE(thiscinfo->back), + DW_BLUE_VALUE(thiscinfo->back))); + if(thiscinfo->hbrush) + DeleteObject(thiscinfo->hbrush); + thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back), + DW_GREEN_VALUE(thiscinfo->back), + DW_BLUE_VALUE(thiscinfo->back))); + SelectObject((HDC)mp1, thiscinfo->hbrush); + return (LONG)thiscinfo->hbrush; + } + } + + } + break; + } + } + + if(ret != TRUE) + { + if(!pOldProc) + return DefWindowProc(hWnd, msg, mp1, mp2); + return CallWindowProc(pOldProc, hWnd, msg, mp1, mp2); + } + return ret; +} + +/* Window procedure for container/listview */ +BOOL CALLBACK _containerwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ + ContainerInfo *cinfo; + + cinfo = (ContainerInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + switch( msg ) + { + case WM_COMMAND: + case WM_NOTIFY: + case WM_MOUSEMOVE: + _wndproc(hWnd, msg, mp1, mp2); + break; + case WM_PAINT: + if(cinfo->cinfo.pOldProc && (cinfo->even != DW_RGB_TRANSPARENT || cinfo->odd != DW_RGB_TRANSPARENT)) + { + RECT rectUpd, rectDestin, rect; + int iItems, iTop, i; + COLORREF c; + + /* Load the default background color for the first pass */ + ListView_SetTextBkColor(hWnd, cinfo->cinfo.back != -1 ? cinfo->cinfo.back : ListView_GetBkColor(hWnd)); + /* get the rectangle to be updated */ + GetUpdateRect(hWnd, &rectUpd, FALSE); + /* allow default processing first */ + CallWindowProc(cinfo->cinfo.pOldProc, hWnd, msg, 0, 0); + /* number of displayed rows */ + iItems = ListView_GetCountPerPage(hWnd); + /* first visible row */ + iTop = ListView_GetTopIndex(hWnd); + + for(i=iTop; i<=(iTop+iItems+1); i++) + { + /* if row rectangle intersects update rectangle then it requires re-drawing */ + if(ListView_GetItemRect(hWnd, i, &rect, LVIR_BOUNDS) && IntersectRect(&rectDestin, &rectUpd, &rect)) + { + /* change text background colour accordingly */ + c = (i % 2) ? cinfo->odd : cinfo->even; + + if(c != DW_RGB_TRANSPARENT) + { + ListView_SetTextBkColor(hWnd, c); + /* invalidate the row rectangle then... */ + InvalidateRect(hWnd, &rectDestin, FALSE); + /* ...force default processing */ + CallWindowProc(cinfo->cinfo.pOldProc, hWnd, msg, 0, 0); + } + } + } + } + break; + case WM_LBUTTONDBLCLK: + case WM_CHAR: + { + LV_ITEM lvi; + int iItem; + + if(LOWORD(mp1) == '\t') + { + if(GetAsyncKeyState(VK_SHIFT) & 0x8000) + _shift_focus_back(hWnd); + else + _shift_focus(hWnd); + return FALSE; + } + + if(msg == WM_CHAR && (char)mp1 != '\r') + break; + + iItem = ListView_GetNextItem(hWnd, -1, LVNI_FOCUSED); + + memset(&lvi, 0, sizeof(LV_ITEM)); + + if(iItem > -1) + { + lvi.iItem = iItem; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(hWnd, &lvi); + } + + { + SignalHandler *tmp = Root; + + while(tmp) + { + 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); + tmp = NULL; + } + if(tmp) + tmp = tmp->next; + } + } + } + break; + case WM_CONTEXTMENU: + { + SignalHandler *tmp = Root; + + while(tmp) + { + if(tmp->message == NM_RCLICK && tmp->window == hWnd) + { + int (*containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction; + LONG x,y; + LV_ITEM lvi; + int iItem; + LVHITTESTINFO lhi; + + dw_pointer_query_pos(&x, &y); + + lhi.pt.x = x; + lhi.pt.y = y; + + MapWindowPoints(HWND_DESKTOP, tmp->window, &lhi.pt, 1); + + iItem = ListView_HitTest(tmp->window, &lhi); + + memset(&lvi, 0, sizeof(LV_ITEM)); + + if(iItem > -1) + { + lvi.iItem = iItem; + lvi.mask = LVIF_PARAM; + + ListView_GetItem(tmp->window, &lvi); + ListView_SetSelectionMark(tmp->window, iItem); + } + + /* 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); + tmp = NULL; + } + if(tmp) + tmp = tmp->next; + } + } + break; + } + + if(!cinfo || !cinfo->cinfo.pOldProc) + return DefWindowProc(hWnd, msg, mp1, mp2); + return CallWindowProc(cinfo->cinfo.pOldProc, hWnd, msg, mp1, mp2); +} + +BOOL CALLBACK _treewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ + ContainerInfo *cinfo; + int ret = -1; + + cinfo = (ContainerInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + switch( msg ) + { + case WM_MOUSEMOVE: + ret = _wndproc(hWnd, msg, mp1, mp2); + break; + case WM_CHAR: + ret = _wndproc(hWnd, msg, mp1, mp2); + if(ret != TRUE && LOWORD(mp1) == '\t') + { + if(GetAsyncKeyState(VK_SHIFT) & 0x8000) + _shift_focus_back(hWnd); + else + _shift_focus(hWnd); + return FALSE; + } + break; + } + + if(ret != TRUE) + { + if(!cinfo || !cinfo->cinfo.pOldProc) + return DefWindowProc(hWnd, msg, mp1, mp2); + return CallWindowProc(cinfo->cinfo.pOldProc, hWnd, msg, mp1, mp2); + } + return ret; +} + +void _changebox(Box *thisbox, int percent, int type) +{ + int z; + + for(z=0;z<thisbox->count;z++) + { + if(thisbox->items[z].type == TYPEBOX) + { + Box *tmp = (Box*)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA); + _changebox(tmp, percent, type); + } + else + { + if(type == DW_HORZ) + { + if(thisbox->items[z].hsize == SIZEEXPAND) + thisbox->items[z].width = (int)(((float)thisbox->items[z].origwidth) * (((float)percent)/((float)100.0))); + } + else + { + if(thisbox->items[z].vsize == SIZEEXPAND) + thisbox->items[z].height = (int)(((float)thisbox->items[z].origheight) * (((float)percent)/((float)100.0))); + } + } + } +} + +void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y) +{ + HWND handle1, handle2; + Box *tmp; + + if(type == DW_HORZ) + { + int newx = x; + float ratio = (float)percent/(float)100.0; + + handle1 = (HWND)dw_window_get_data(hwnd, "_dw_topleft"); + handle2 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright"); + tmp = (Box *)GetWindowLongPtr(handle1, GWLP_USERDATA); + + newx = (int)((float)newx * ratio) - (SPLITBAR_WIDTH/2); + + ShowWindow(handle1, SW_HIDE); + ShowWindow(handle2, SW_HIDE); + + MoveWindow(handle1, 0, 0, newx, y, FALSE); + _do_resize(tmp, newx - 1, y - 1); + + tmp = (Box *)GetWindowLongPtr(handle2, GWLP_USERDATA); + + newx = x - newx - SPLITBAR_WIDTH; + + MoveWindow(handle2, x - newx, 0, newx, y, FALSE); + _do_resize(tmp, newx - 1, y - 1); + + dw_window_set_data(hwnd, "_dw_start", (void *)newx); + } + else + { + int newy = y; + float ratio = (float)(100.0-percent)/(float)100.0; + + handle1 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright"); + handle2 = (HWND)dw_window_get_data(hwnd, "_dw_topleft"); + tmp = (Box *)GetWindowLongPtr(handle1, GWLP_USERDATA); + + newy = (int)((float)newy * ratio) - (SPLITBAR_WIDTH/2); + + ShowWindow(handle1, SW_HIDE); + ShowWindow(handle2, SW_HIDE); + + MoveWindow(handle1, 0, y - newy, x, newy, FALSE); + _do_resize(tmp, x - 1, newy - 1); + + tmp = (Box *)GetWindowLongPtr(handle2, GWLP_USERDATA); + + newy = y - newy - SPLITBAR_WIDTH; + + MoveWindow(handle2, 0, 0, x, newy, FALSE); + _do_resize(tmp, x - 1, newy - 1); + + dw_window_set_data(hwnd, "_dw_start", (void *)newy); + } + + ShowWindow(handle1, SW_SHOW); + ShowWindow(handle2, SW_SHOW); +} + +/* This handles any activity on the scrollbox */ +BOOL CALLBACK _scrollwndproc(HWND hwnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ + switch (msg) + { + case WM_HSCROLL: + case WM_VSCROLL: + { + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + SCROLLINFO hsi, vsi, *si = &hsi; + int bar = SB_HORZ; + int which = LOWORD(mp1); + + /* Initialize the scroll info structs */ + vsi.cbSize = hsi.cbSize = sizeof(SCROLLINFO); + vsi.fMask = hsi.fMask = SIF_POS | SIF_RANGE | SIF_PAGE; + + /* Save the current scroll positions */ + GetScrollInfo(hwnd, SB_HORZ, &hsi); + GetScrollInfo(hwnd, SB_VERT, &vsi); + + if(msg == WM_VSCROLL) + { + bar = SB_VERT; + si = &vsi; + } + + switch(which) + { + case SB_THUMBTRACK: + si->nPos = HIWORD(mp1); + break; + /*case SB_PAGEDOWN:*/ + case SB_PAGELEFT: + si->nPos = si->nPos - si->nPage; + if(si->nPos < 0) + si->nPos = 0; + break; + /*case SB_PAGEUP:*/ + case SB_PAGERIGHT: + si->nPos = si->nPos + si->nPage; + if(si->nPos > (si->nMax - si->nPage) + 1) + si->nPos = (si->nMax - si->nPage) + 1; + break; + /*case SB_LINEDOWN:*/ + case SB_LINELEFT: + si->nPos = si->nPos - 1; + if(si->nPos < si->nMin) + si->nPos = si->nMin; + break; + /*case SB_LINEUP:*/ + case SB_LINERIGHT: + si->nPos = si->nPos + 1; + if(si->nPos > (si->nMax - si->nPage) + 1) + si->nPos = (si->nMax - si->nPage) + 1; + break; + } + + /* Position the scrolled box */ + vsi.fMask = hsi.fMask = SIF_POS | SIF_DISABLENOSCROLL; + SetWindowPos(cinfo->combo, 0, -hsi.nPos, -vsi.nPos, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + SetScrollInfo(hwnd, bar, si, TRUE); + } + break; + } + return DefWindowProc(hwnd, msg, mp1, mp2); +} + +/* This handles any activity on the splitbars (sizers) */ +BOOL CALLBACK _splitwndproc(HWND hwnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ + switch (msg) + { + case WM_ACTIVATE: + case WM_SETFOCUS: + return FALSE; + + 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"); + + 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))); + + dw_window_get_pos_size(hwnd, NULL, NULL, &cx, &cy); + + if(type == DW_HORZ) + Rectangle(hdcPaint, cx - start - SPLITBAR_WIDTH, 0, cx - start, cy); + else + Rectangle(hdcPaint, 0, start, cx, start + SPLITBAR_WIDTH); + + SelectObject(hdcPaint, oldBrush); + DeleteObject(SelectObject(hdcPaint, oldPen)); + ReleaseDC(hwnd, hdcPaint); + } + EndPaint(hwnd, &ps); + } + break; + case WM_LBUTTONDOWN: + { + SetCapture(hwnd); + break; + } + case WM_LBUTTONUP: + { + if(GetCapture() == hwnd) + ReleaseCapture(); + } + break; + case WM_MOUSEMOVE: + { + float *percent = (float *)dw_window_get_data(hwnd, "_dw_percent"); + int type = (int)dw_window_get_data(hwnd, "_dw_type"); + int start; + + if(type == DW_HORZ) + SetCursor(LoadCursor(NULL, IDC_SIZEWE)); + else + SetCursor(LoadCursor(NULL, IDC_SIZENS)); + + if(GetCapture() == hwnd && percent) + { + POINT point; + RECT rect; + static POINT lastpoint; + + GetCursorPos(&point); + GetWindowRect(hwnd, &rect); + + if(memcmp(&point, &lastpoint, sizeof(POINT))) + { + if(PtInRect(&rect, point)) + { + int width = (rect.right - rect.left); + int height = (rect.bottom - rect.top); + + if(type == DW_HORZ) + { + start = point.x - rect.left; + if(width - SPLITBAR_WIDTH > 1 && start < width - SPLITBAR_WIDTH) + *percent = ((float)start / (float)(width - SPLITBAR_WIDTH)) * 100.0; + } + else + { + start = point.y - rect.top; + if(height - SPLITBAR_WIDTH > 1 && start < height - SPLITBAR_WIDTH) + *percent = ((float)start / (float)(height - SPLITBAR_WIDTH)) * 100.0; + } + _handle_splitbar_resize(hwnd, *percent, type, width, height); + } + memcpy(&lastpoint, &point, sizeof(POINT)); + } + } + break; + } + } + return DefWindowProc(hwnd, msg, mp1, mp2); +} + +/* This handles drawing the status text areas */ +BOOL CALLBACK _statuswndproc(HWND hwnd, UINT msg, WPARAM mp1, LPARAM mp2) +{ + switch (msg) + { + case WM_MOUSEMOVE: + _wndproc(hwnd, msg, mp1, mp2); + break; + case WM_SETTEXT: + { + /* Make sure the control redraws when there is a text change */ + int ret = (int)DefWindowProc(hwnd, msg, mp1, mp2); + + InvalidateRgn(hwnd, NULL, TRUE); + return ret; + } + case WM_PAINT: + { + HDC hdcPaint; + PAINTSTRUCT ps; + RECT rc; + unsigned long cx, cy; + char tempbuf[1024] = ""; + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + HFONT hfont = _acquire_font(hwnd, cinfo ? cinfo->fontname : NULL); + HFONT oldfont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); + + dw_window_get_pos_size(hwnd, NULL, NULL, &cx, &cy); + GetWindowText(hwnd, tempbuf, 1024); + + 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); + if(hfont && oldfont) + SelectObject(hdcPaint, oldfont); + if(hfont) + DeleteObject(hfont); + EndPaint(hwnd, &ps); + } + return FALSE; + } + return DefWindowProc(hwnd, msg, mp1, mp2); +} + +/* Function: _BtProc + * Abstract: Subclass procedure for buttons + */ + +BOOL CALLBACK _BtProc(HWND hwnd, ULONG msg, WPARAM mp1, LPARAM mp2) +{ + BubbleButton *bubble; + POINT point; + RECT rect; + WNDPROC pOldProc; + + bubble = (BubbleButton *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + if ( !bubble ) + return DefWindowProc(hwnd, msg, mp1, mp2); + + /* We must save a pointer to the old + * window procedure because if a signal + * handler attached here destroys this + * window it will then be invalid. + */ + pOldProc = bubble->pOldProc; + + switch(msg) + { + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORBTN: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORMSGBOX: + case WM_CTLCOLORSCROLLBAR: + case WM_CTLCOLORDLG: + _wndproc(hwnd, msg, mp1, mp2); + break; + case WM_SETFOCUS: + _wndproc(hwnd, msg, mp1, mp2); + break; + case WM_LBUTTONUP: + { + SignalHandler *tmp = Root; + + /* Find any callbacks for this function */ + while(tmp) + { + if(tmp->message == WM_COMMAND) + { + int (*clickfunc)(HWND, void *) = tmp->signalfunction; + + /* Make sure it's the right window, and the right ID */ + if(tmp->window == hwnd) + { + if(bubble->checkbox) + in_checkbox_handler = 1; + + clickfunc(tmp->window, tmp->data); + + if(bubble->checkbox) + in_checkbox_handler = 0; + tmp = NULL; + } + } + if(tmp) + tmp= tmp->next; + } + } + break; + case WM_CHAR: + { + /* A button press should also occur for an ENTER or SPACE press + * while the button has the active input focus. + */ + if(LOWORD(mp1) == '\r' || LOWORD(mp1) == ' ') + { + SignalHandler *tmp = Root; + + /* Find any callbacks for this function */ + while(tmp) + { + if(tmp->message == WM_COMMAND) + { + int (*clickfunc)(HWND, void *) = tmp->signalfunction; + + /* Make sure it's the right window, and the right ID */ + if(tmp->window == hwnd) + { + clickfunc(tmp->window, tmp->data); + tmp = NULL; + } + } + if(tmp) + tmp= tmp->next; + } + } + if(LOWORD(mp1) == '\t') + { + if(GetAsyncKeyState(VK_SHIFT) & 0x8000) + _shift_focus_back(hwnd); + else + _shift_focus(hwnd); + return FALSE; + } + } + break; + case WM_KEYDOWN: + if(mp1 == VK_LEFT || mp1 == VK_UP) + _shift_focus_back(hwnd); + if(mp1 == VK_RIGHT || mp1 == VK_DOWN) + _shift_focus(hwnd); + break; + } + + if ( !pOldProc ) + return DefWindowProc(hwnd, msg, mp1, mp2); + return CallWindowProc(pOldProc, hwnd, msg, mp1, mp2); +} + +/* This function recalculates a notebook page for example + * during switching of notebook pages. + */ +void _resize_notebook_page(HWND handle, int pageid) +{ + RECT rect; + NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); + + if(array && array[pageid]) + { + Box *box = (Box *)GetWindowLongPtr(array[pageid]->hwnd, GWLP_USERDATA); + + GetClientRect(handle,&rect); + TabCtrl_AdjustRect(handle,FALSE,&rect); + MoveWindow(array[pageid]->hwnd, rect.left, rect.top, + rect.right - rect.left, rect.bottom-rect.top, TRUE); + if(box && box->count) + { + ShowWindow(box->items[0].hwnd, SW_HIDE); + _do_resize(box, rect.right - rect.left, rect.bottom - rect.top); + ShowWindow(box->items[0].hwnd, SW_SHOW); + } + + ShowWindow(array[pageid]->hwnd, SW_SHOWNORMAL); + } +} + +void _create_tooltip(HWND handle, char *text) +{ + /* Create a tooltip. */ + HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST, + TOOLTIPS_CLASS, NULL, + WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + handle, NULL, DWInstance,NULL); + TOOLINFO ti = { 0 }; + + SetWindowPos(hwndTT, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + + /* Set up "tool" information. + * In this case, the "tool" is the entire parent window. + */ + ti.cbSize = sizeof(TOOLINFO); + ti.uFlags = TTF_SUBCLASS; + ti.hwnd = handle; + ti.hinst = DWInstance; + ti.lpszText = text; + GetClientRect(handle, &ti.rect); + + /* Associate the tooltip with the "tool" window. */ + SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti); +} + +#ifndef GDIPLUS +/* This function determines the handle for a supplied image filename + */ +int _dw_get_image_handle(char *filename, HANDLE *icon, HBITMAP *hbitmap) +{ + int len, windowtype = 0; + char *file = malloc(strlen(filename) + 5); + + *hbitmap = 0; + *icon = 0; + + if (!file) + { + return 0; + } + + strcpy(file, filename); + + /* check if we can read from this file (it exists and read permission) */ + if (access(file, 04) == 0) + { + len = strlen( file ); + if ( len < 4 ) + { + free(file); + return 0; + } + if ( stricmp( file + len - 4, ".ico" ) == 0 ) + { + *icon = LoadImage(NULL, file, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + windowtype = BS_ICON; + } + else if ( stricmp( file + len - 4, ".bmp" ) == 0 ) + { + *hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + windowtype = BS_BITMAP; + } + else if ( stricmp( file + len - 4, ".png" ) == 0 ) + { + *hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + windowtype = BS_BITMAP; + } + free(file); + } + else + { + /* Try with .ico extension first...*/ + strcat(file, ".ico"); + if (access(file, 04) == 0) + { + *icon = LoadImage(NULL, file, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + windowtype = BS_ICON; + } + else + { + strcpy(file, filename); + strcat(file, ".bmp"); + if (access(file, 04) == 0) + { + *hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + windowtype = BS_BITMAP; + } + } + free(file); + } + return windowtype; +} +#endif + +/* Initialize thread local values to the defaults */ +void _init_thread(void) +{ + COLORREF foreground = RGB(128,128,128); + COLORREF background = DW_RGB_TRANSPARENT; + 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: + * newthread: True if this is the only thread. + * False if there is already a message loop running. + */ +int API dw_init(int newthread, int argc, char *argv[]) +{ + WNDCLASS wc; + int z; + INITCOMMONCONTROLSEX icc; + char *fname, *alttmpdir; + HFONT oldfont; + struct GdiplusStartupInput si; + + /* Initialize our thread local storage */ + _foreground = TlsAlloc(); + _background = TlsAlloc(); + _hPen = TlsAlloc(); + _hBrush = TlsAlloc(); + _init_thread(); + + icc.dwSize = sizeof(INITCOMMONCONTROLSEX); + icc.dwICC = ICC_WIN95_CLASSES|ICC_DATE_CLASSES; + + InitCommonControlsEx(&icc); + + memset(lookup, 0, sizeof(HICON) * ICON_INDEX_LIMIT); + + /* Register the generic Dynamic Windows class */ + memset(&wc, 0, sizeof(WNDCLASS)); + wc.style = CS_DBLCLKS; + wc.lpfnWndProc = (WNDPROC)_wndproc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 32; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = ClassName; + + RegisterClass(&wc); + + /* Register the splitbar control */ + memset(&wc, 0, sizeof(WNDCLASS)); + wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)_splitwndproc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = SplitbarClassName; + + RegisterClass(&wc); + + /* Register the scroller control */ + memset(&wc, 0, sizeof(WNDCLASS)); + wc.style = CS_DBLCLKS; + wc.lpfnWndProc = (WNDPROC)_scrollwndproc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 32; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = ScrollClassName; + + RegisterClass(&wc); + + /* Register a frame control like on OS/2 */ + memset(&wc, 0, sizeof(WNDCLASS)); + wc.style = CS_DBLCLKS; + wc.lpfnWndProc = (WNDPROC)_framewndproc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 32; + wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_3DFACE); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.lpszMenuName = NULL; + wc.lpszClassName = FRAMECLASSNAME; + + RegisterClass(&wc); + + /* Register HTML renderer class */ + memset(&wc, 0, sizeof(WNDCLASS)); + wc.lpfnWndProc = (WNDPROC)_browserWindowProc; + wc.lpszClassName = BrowserClassName; + wc.style = CS_HREDRAW|CS_VREDRAW; + RegisterClass(&wc); + + /* Create a set of brushes using the default OS/2 and DOS colors */ + for(z=0;z<18;z++) + _colors[z] = CreateSolidBrush(RGB(_red[z],_green[z],_blue[z])); + + /* Register an Object Windows class like OS/2 and Win2k+ + * so similar functionality can be used on earlier releases + * of Windows. + */ + memset(&wc, 0, sizeof(WNDCLASS)); + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)_wndproc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hbrBackground = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.lpszMenuName = NULL; + wc.lpszClassName = ObjectClassName; + + RegisterClass(&wc); + + /* Since Windows 95/98/NT don't have a HWND_OBJECT class + * also known as a input only window, I will create a + * temporary window that isn't visible and really does nothing + * except temporarily hold the child windows before they are + * packed into their correct parent. + */ + + DW_HWND_OBJECT = CreateWindow(ObjectClassName, "", 0, 0, 0, + 0, 0, HWND_DESKTOP, NULL, DWInstance, NULL); + + if(!DW_HWND_OBJECT) + { + dw_messagebox("Dynamic Windows", DW_MB_OK|DW_MB_ERROR, "Could not initialize the object window. error code %d", GetLastError()); + exit(1); + } + + /* 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); + + OleInitialize(NULL); + + /* + * Get an alternate temporary directory in case TMP doesn't exist + */ + if ( (alttmpdir = getenv( "TEMP" ) ) == NULL ) + { + strcpy( _dw_alternate_temp_dir, "c:\\tmp" ); + } + else + { + strncpy( _dw_alternate_temp_dir, alttmpdir, MAX_PATH ); + } + /* + * Get screen size. Used to make calls to dw_screen_width() + * and dw_screen-height() quicker, but to alos limit the + * default size of windows. + */ + screenx = GetSystemMetrics(SM_CXSCREEN); + screeny = GetSystemMetrics(SM_CYSCREEN); + +#ifdef GDIPLUS + /* Setup GDI+ */ + si.GdiplusVersion = 1; + si.DebugEventCallback = NULL; + si.SuppressBackgroundThread = FALSE; + si.SuppressExternalCodecs = FALSE; + GdiplusStartup(&gdiplusToken, &si, NULL); +#endif + return 0; +} + +/* + * Runs a message loop for Dynamic Windows. + */ +void API dw_main(void) +{ + MSG msg; + + _dwtid = dw_thread_id(); + + while(GetMessage(&msg, NULL, 0, 0)) + { + if(msg.hwnd == NULL && msg.message == WM_TIMER) + _wndproc(msg.hwnd, msg.message, msg.wParam, msg.lParam); + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + +/* + * Runs a message loop for Dynamic Windows, for a period of milliseconds. + * Parameters: + * milliseconds: Number of milliseconds to run the loop for. + */ +void API dw_main_sleep(int milliseconds) +{ + MSG msg; + double start = (double)clock(); + + while(((clock() - start) / (CLOCKS_PER_SEC/1000)) <= milliseconds) + { + if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) + { + GetMessage(&msg, NULL, 0, 0); + if(msg.hwnd == NULL && msg.message == WM_TIMER) + _wndproc(msg.hwnd, msg.message, msg.wParam, msg.lParam); + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else + Sleep(1); + } +} + +/* + * Processes a single message iteration and returns. + */ +void API dw_main_iteration(void) +{ + MSG msg; + + _dwtid = dw_thread_id(); + + if(GetMessage(&msg, NULL, 0, 0)) + { + if(msg.hwnd == NULL && msg.message == WM_TIMER) + _wndproc(msg.hwnd, msg.message, msg.wParam, msg.lParam); + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + +/* + * Free's memory allocated by dynamic windows. + * Parameters: + * ptr: Pointer to dynamic windows allocated + * memory to be free()'d. + */ +void API dw_free(void *ptr) +{ + free(ptr); +} + +/* + * Allocates and initializes a dialog struct. + * Parameters: + * data: User defined data to be passed to functions. + */ +DWDialog * API dw_dialog_new(void *data) +{ + DWDialog *tmp = malloc(sizeof(DWDialog)); + + tmp->eve = dw_event_new(); + dw_event_reset(tmp->eve); + tmp->data = data; + tmp->done = FALSE; + tmp->result = NULL; + + return tmp; +} + +/* + * Accepts a dialog struct and returns the given data to the + * initial called of dw_dialog_wait(). + * Parameters: + * dialog: Pointer to a dialog struct aquired by dw_dialog_new). + * result: Data to be returned by dw_dialog_wait(). + */ +int API dw_dialog_dismiss(DWDialog *dialog, void *result) +{ + dialog->result = result; + dw_event_post(dialog->eve); + dialog->done = TRUE; + return 0; +} + +/* + * Accepts a dialog struct waits for dw_dialog_dismiss() to be + * called by a signal handler with the given dialog struct. + * Parameters: + * dialog: Pointer to a dialog struct aquired by dw_dialog_new). + */ +void * API dw_dialog_wait(DWDialog *dialog) +{ + MSG msg; + void *tmp; + + while (GetMessage(&msg,NULL,0,0)) + { + if(msg.hwnd == NULL && msg.message == WM_TIMER) + _wndproc(msg.hwnd, msg.message, msg.wParam, msg.lParam); + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + if(dialog->done) + break; + } + dw_event_close(&dialog->eve); + tmp = dialog->result; + free(dialog); + return tmp; +} + +/* + * Displays a debug message on the console... + * Parameters: + * format: printf style format string. + * ...: Additional variables for use in the format. + */ +void API dw_debug(char *format, ...) +{ + va_list args; + char outbuf[1025] = {0}; + + va_start(args, format); + vsnprintf(outbuf, 1024, format, args); + va_end(args); + + OutputDebugString(outbuf); +} + +/* + * Displays a Message Box with given text and title.. + * Parameters: + * title: The title of the message box. + * format: printf style format string. + * ...: Additional variables for use in the format. + */ +int API dw_messagebox(char *title, int flags, char *format, ...) +{ + va_list args; + char outbuf[1024]; + int rc; + + va_start(args, format); + vsnprintf(outbuf, 1024, format, args); + va_end(args); + + rc = MessageBox(HWND_DESKTOP, outbuf, title, flags); + if(rc == IDOK) + return DW_MB_RETURN_OK; + else if(rc == IDYES) + return DW_MB_RETURN_YES; + else if(rc == IDNO) + return DW_MB_RETURN_NO; + else if(rc == IDCANCEL) + return DW_MB_RETURN_CANCEL; + else return 0; +} + +/* + * Minimizes or Iconifies a top-level window. + * Parameters: + * handle: The window handle to minimize. + */ +int API dw_window_minimize(HWND handle) +{ + return ShowWindow(handle, SW_MINIMIZE); +} + +/* + * Makes the window topmost. + * Parameters: + * handle: The window handle to make topmost. + */ +int API dw_window_raise(HWND handle) +{ + return SetWindowPos(handle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); +} + +/* + * Makes the window bottommost. + * Parameters: + * handle: The window handle to make bottommost. + */ +int API dw_window_lower(HWND handle) +{ + return SetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); +} + +/* + * Makes the window visible. + * Parameters: + * handle: The window handle to make visible. + */ +int API dw_window_show(HWND handle) +{ + int rc = ShowWindow(handle, SW_SHOW); + SetFocus(handle); + _initial_focus(handle); + return rc; +} + +/* + * Makes the window invisible. + * Parameters: + * handle: The window handle to make visible. + */ +int API dw_window_hide(HWND handle) +{ + return ShowWindow(handle, SW_HIDE); +} + +/* + * Destroys a window and all of it's children. + * Parameters: + * handle: The window handle to destroy. + */ +int API dw_window_destroy(HWND handle) +{ + HWND parent = GetParent(handle); + Box *thisbox = (Box *)GetWindowLongPtr(parent, GWLP_USERDATA); + HMENU menu = GetMenu(handle); + + if(menu) + _free_menu_data(menu); + + /* If it is a desktop window let WM_DESTROY handle it */ + if(parent != HWND_DESKTOP) + { + /* If the parent box has items... + * try to remove it from the layout + */ + if(thisbox && thisbox->count) + { + int z, index = -1; + Item *tmpitem, *thisitem = thisbox->items; + + for(z=0;z<thisbox->count;z++) + { + if(thisitem[z].hwnd == handle) + index = z; + } + + if(index == -1) + return 0; + + tmpitem = malloc(sizeof(Item)*(thisbox->count-1)); + + /* Copy all but the current entry to the new list */ + for(z=0;z<index;z++) + { + tmpitem[z] = thisitem[z]; + } + for(z=index+1;z<thisbox->count;z++) + { + tmpitem[z-1] = thisitem[z]; + } + + thisbox->items = tmpitem; + free(thisitem); + thisbox->count--; + } + _free_window_memory(handle, 0); + EnumChildWindows(handle, _free_window_memory, 0); + } + return DestroyWindow(handle); +} + +/* Causes entire window to be invalidated and redrawn. + * Parameters: + * handle: Toplevel window handle to be redrawn. + */ +void API dw_window_redraw(HWND handle) +{ + Box *mybox = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA); + + if(mybox) + { + RECT rect; + int istoplevel = (GetParent(handle) == HWND_DESKTOP); + + GetClientRect(handle, &rect); + + ShowWindow(istoplevel ? mybox->items[0].hwnd : handle, SW_HIDE); + _do_resize(mybox, rect.right - rect.left, rect.bottom - rect.top); + ShowWindow(istoplevel ? mybox->items[0].hwnd : handle, SW_SHOW); + } +} + +int instring(char *text, char *buffer) +{ + int z, len = strlen(text), buflen = strlen(buffer); + + if(buflen > len) + { + for(z=0;z<=(buflen-len);z++) + { + if(memcmp(text, &buffer[z], len) == 0) + return z; + } + } + return 0; +} + +/* + * Changes a window's parent to newparent. + * Parameters: + * handle: The window handle to destroy. + * newparent: The window's new parent window. + */ +void API dw_window_reparent(HWND handle, HWND newparent) +{ + SetParent(handle, newparent); +} + +LOGFONT _get_logfont(HDC hdc, char *fontname) +{ + int Italic, Bold; + char *myFontName; + int z, size = 9; + LOGFONT lf = {0}; + + for(z=0;z<strlen(fontname);z++) + { + if(fontname[z]=='.') + break; + } + size = atoi(fontname); + lf.lfHeight = -MulDiv(size, GetDeviceCaps(hdc, LOGPIXELSY), 72); + Italic = instring(" Italic", &fontname[z+1]); + Bold = instring(" Bold", &fontname[z+1]); + lf.lfWidth = 0; + lf.lfEscapement = 0; + lf.lfOrientation = 0; + lf.lfItalic = Italic ? TRUE : FALSE; + lf.lfUnderline = 0; + lf.lfStrikeOut = 0; + lf.lfWeight = Bold ? FW_BOLD : FW_NORMAL; + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfOutPrecision = 0; + lf.lfClipPrecision = 0; + lf.lfQuality = DEFAULT_QUALITY; + lf.lfPitchAndFamily = DEFAULT_PITCH | FW_DONTCARE; + /* + * remove any font modifiers + */ + myFontName = strdup(&fontname[z+1]); + if(Italic) + myFontName[Italic] = 0; + if(Bold) + myFontName[Bold] = 0; + strncpy(lf.lfFaceName, myFontName, sizeof(lf.lfFaceName)-1); + free(myFontName); + return lf; +} + +/* Create a duplicate of an existing font handle + * that is safe to call DeleteObject() on. + */ +HFONT _DupFontHandle(HFONT hfont) +{ + LOGFONT lf = {0}; + return GetObject(hfont, sizeof(lf), &lf) ? CreateFontIndirect(&lf) : NULL; +} + +/* Create a font handle from specified font name.. + * or return a handle to the default font. + */ +HFONT _acquire_font2(HDC hdc, char *fontname) +{ + HFONT hfont = 0; + + if(fontname != DefaultFont && fontname[0]) + { + LOGFONT lf = _get_logfont(hdc, fontname); + hfont = CreateFontIndirect(&lf); + } + if(!hfont && _DefaultFont) + hfont = _DupFontHandle(_DefaultFont); + if(!hfont) + hfont = GetStockObject(DEFAULT_GUI_FONT); + return hfont; +} + +/* Create a font handle from specified font name.. + * or return a handle to the default font. + */ +HFONT _acquire_font(HWND handle, char *fontname) +{ + HDC hdc = GetDC(handle); + HFONT hfont = _acquire_font2(hdc, fontname); + ReleaseDC(handle, hdc); + return hfont; +} + +/* + * Sets the default font used on text based widgets. + * Parameters: + * fontname: Font name in Dynamic Windows format. + */ +void API dw_font_set_default(char *fontname) +{ + HFONT oldfont = _DefaultFont; + + _DefaultFont = _acquire_font(HWND_DESKTOP, fontname); + if(oldfont) + { + DeleteObject(oldfont); + } +} + +/* + * Sets the font used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * fontname: Name and size of the font in the form "size.fontname" + */ +int API dw_window_set_font(HWND handle, char *fontname) +{ + HFONT hfont, oldfont; + ColorInfo *cinfo; + char tmpbuf[100]; + + cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + + GetClassName(handle, tmpbuf, 99); + if ( strnicmp( tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1) == 0 ) + { + /* groupbox */ + Box *thisbox = (Box *)GetWindowLongPtr( handle, GWLP_USERDATA ); + if ( thisbox && thisbox->grouphwnd != (HWND)NULL ) + { + handle = thisbox->grouphwnd; + } + } + + /* This needs to be after we get the correct handle */ + oldfont = (HFONT)SendMessage(handle, WM_GETFONT, 0, 0); + hfont = _acquire_font(handle, fontname); + + if (fontname) + { + if(cinfo) + { + strcpy(cinfo->fontname, fontname); + if(!oldfont) + oldfont = cinfo->hfont; + cinfo->hfont = hfont; + } + else + { + cinfo = calloc(1, sizeof(ColorInfo)); + cinfo->fore = cinfo->back = -1; + + strncpy(cinfo->fontname, fontname, 127); + + cinfo->pOldProc = SubclassWindow(handle, _colorwndproc); + SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo); + } + } + SendMessage(handle, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE); + if(oldfont) + DeleteObject(oldfont); + return 0; +} + +/* Allows the user to choose a font using the system's font chooser dialog. + * Parameters: + * currfont: current font + * Returns: + * A malloced buffer with the selected font or NULL on error. + */ +char * API dw_font_choose(char *currfont) +{ + CHOOSEFONT cf = { 0 }; + LOGFONT lf = { 0 }; + char *str = NULL; + char *bold = ""; + char *italic = ""; + + if(currfont && *currfont) + lf = _get_logfont(NULL, currfont); + + cf.lStructSize = sizeof(cf); + cf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT; + cf.lpLogFont = &lf; + + if(ChooseFont(&cf)) + { + str = (char *)calloc( 101, 1 ); + if ( str ) + { + int height; + HDC hdc = GetDC(NULL); + + if ( lf.lfWeight > FW_MEDIUM ) + bold = " Bold"; + if ( lf.lfItalic ) + italic = " Italic"; + height = MulDiv(abs(lf.lfHeight), 72, GetDeviceCaps (hdc, LOGPIXELSY)); + ReleaseDC(NULL, hdc); + _snprintf( str, 100, "%d.%s%s%s", height, lf.lfFaceName, bold, italic ); + } + } + return str; +} + +/* + * Gets the font used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * fontname: Name and size of the font in the form "size.fontname" + */ +char * API dw_window_get_font(HWND handle) +{ + HFONT oldfont = NULL; + char *str = NULL; + char *bold = ""; + char *italic = ""; + LOGFONT lf = { 0 }; + Box *thisbox; + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + if ( strnicmp( tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1) == 0 ) + { + /* groupbox */ + thisbox = (Box *)GetWindowLongPtr( handle, GWLP_USERDATA ); + if ( thisbox && thisbox->grouphwnd != (HWND)NULL ) + { + handle = thisbox->grouphwnd; + } + } + oldfont = (HFONT)SendMessage(handle, WM_GETFONT, 0, 0); + if ( GetObject( oldfont, sizeof(lf), &lf ) ) + { + str = (char *)calloc( 100, 1 ); + if ( str ) + { + int height; + HDC hdc = GetDC(handle); + + if ( lf.lfWeight > FW_MEDIUM ) + bold = " Bold"; + if ( lf.lfItalic ) + 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 ); + } + } + if ( oldfont ) + DeleteObject( oldfont ); + return str; +} + +/* + * Sets the colors used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * fore: Foreground color in RGB format. + * back: Background color in RGB format. + */ +int API dw_window_set_color(HWND handle, ULONG fore, ULONG back) +{ + ColorInfo *cinfo; + Box *thisbox; + char tmpbuf[100]; + + cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW))==0) + { + cinfo->fore = fore = _internal_color(fore); + cinfo->back = back = _internal_color(back); + + ListView_SetTextColor(handle, RGB(DW_RED_VALUE(fore), + DW_GREEN_VALUE(fore), + DW_BLUE_VALUE(fore))); + ListView_SetTextBkColor(handle, RGB(DW_RED_VALUE(back), + DW_GREEN_VALUE(back), + DW_BLUE_VALUE(back))); + ListView_SetBkColor(handle, RGB(DW_RED_VALUE(back), + DW_GREEN_VALUE(back), + DW_BLUE_VALUE(back))); + InvalidateRgn(handle, NULL, TRUE); + return TRUE; + } + else if ( strnicmp( tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)) == 0 ) + { + /* groupbox */ + thisbox = (Box *)GetWindowLongPtr( handle, GWLP_USERDATA ); + if ( thisbox && thisbox->grouphwnd != (HWND)NULL ) + { + thisbox->cinfo.fore = fore; + thisbox->cinfo.back = back; + } + } + + if(cinfo) + { + cinfo->fore = fore; + cinfo->back = back; + } + else + { + cinfo = calloc(1, sizeof(ColorInfo)); + + cinfo->fore = fore; + cinfo->back = back; + + cinfo->pOldProc = SubclassWindow(handle, _colorwndproc); + SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo); + } + InvalidateRgn(handle, NULL, TRUE); + return TRUE; +} + +/* + * Sets the font used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * border: Size of the window border in pixels. + */ +int API dw_window_set_border(HWND handle, int border) +{ + return 0; +} + +/* + * Captures the mouse input to this window. + * Parameters: + * handle: Handle to receive mouse input. + */ +void API dw_window_capture(HWND handle) +{ + SetCapture(handle); +} + +/* + * Releases previous mouse capture. + */ +void API dw_window_release(void) +{ + ReleaseCapture(); +} + +/* + * Changes the appearance of the mouse pointer. + * Parameters: + * handle: Handle to widget for which to change. + * cursortype: ID of the pointer you want. + */ +void API dw_window_set_pointer(HWND handle, int pointertype) +{ + HCURSOR cursor = pointertype < 65536 ? LoadCursor(NULL, MAKEINTRESOURCE(pointertype)) : (HCURSOR)pointertype; + + if(!pointertype) + dw_window_set_data(handle, "_dw_cursor", 0); + else + { + dw_window_set_data(handle, "_dw_cursor", (void *)cursor); + SetCursor(cursor); + } +} + +/* + * Create a new Window Frame. + * Parameters: + * owner: The Owner's window handle or HWND_DESKTOP. + * title: The Window title. + * flStyle: Style flags, see the DW reference. + */ +HWND API dw_window_new(HWND hwndOwner, char *title, ULONG flStyle) +{ + HWND hwndframe; + Box *newbox = calloc(sizeof(Box), 1); + ULONG flStyleEx = 0; + + newbox->pad = 0; + newbox->type = DW_VERT; + newbox->count = 0; + newbox->cinfo.fore = newbox->cinfo.back = -1; + + /* Hmm, the "correct" way doesn't seem to be + * working, but the old hackish SetParent() + * at the bottom seems to work, so I'll leave + * it like this for now. + */ +#if 0 + if(hwndOwner) + flStyleEx |= WS_EX_MDICHILD; +#endif + + if(!(flStyle & WS_CAPTION)) + flStyle |= WS_POPUPWINDOW; + + if(flStyle & DW_FCF_TASKLIST) + { + ULONG newflags = (flStyle | WS_CLIPCHILDREN) & ~DW_FCF_TASKLIST; + + hwndframe = CreateWindowEx(flStyleEx, ClassName, title, newflags, CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner, NULL, DWInstance, NULL); + } + else + { + flStyleEx |= WS_EX_TOOLWINDOW; + + hwndframe = CreateWindowEx(flStyleEx, ClassName, title, flStyle | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner, NULL, DWInstance, NULL); + } + SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox); + + if(hwndOwner) + SetParent(hwndframe, hwndOwner); + + return hwndframe; +} + +/* + * Create a new Box to be packed. + * Parameters: + * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). + * pad: Number of pixels to pad around the box. + */ +HWND API dw_box_new(int type, int pad) +{ + Box *newbox = calloc(sizeof(Box), 1); + HWND hwndframe; + + newbox->pad = pad; + newbox->type = type; + newbox->count = 0; + newbox->grouphwnd = (HWND)NULL; + newbox->cinfo.fore = newbox->cinfo.back = -1; + + hwndframe = CreateWindow(FRAMECLASSNAME, + "", + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + NULL, + DWInstance, + NULL); + + newbox->cinfo.pOldProc = SubclassWindow(hwndframe, _colorwndproc); + newbox->cinfo.fore = newbox->cinfo.back = -1; + + SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox); + return hwndframe; +} + +/* + * Create a new scroll Box to be packed. + * Parameters: + * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). + * pad: Number of pixels to pad around the box. + */ +HWND API dw_scrollbox_new(int type, int pad) +{ + ColorInfo *cinfo = calloc(sizeof(ColorInfo), 1); + HWND hwndframe, box = dw_box_new(type, pad); + HWND tmpbox = dw_box_new(DW_VERT, 0); + dw_box_pack_start(tmpbox, box, 1, 1, TRUE, TRUE, 0); + + cinfo->fore = cinfo->back = -1; + + hwndframe = CreateWindow(ScrollClassName, + "", + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL, + 0,0,2000,1000, + DW_HWND_OBJECT, + NULL, + DWInstance, + NULL); + + cinfo->buddy = box; + cinfo->combo = tmpbox; + SetParent(tmpbox, hwndframe); + SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)cinfo); + return hwndframe; +} + +/* + * Returns the position of the scrollbar in the scrollbox + * Parameters: + * handle: Handle to the scrollbox to be queried. + * orient: The vertical or horizontal scrollbar. + */ +int API dw_scrollbox_get_pos( HWND handle, int orient ) +{ + SCROLLINFO si; + int bar = SB_HORZ; + + if(orient == DW_VERT) + { + bar = SB_VERT; + } + + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS; + + /* Get the current scroll positions */ + if(!GetScrollInfo(handle, bar, &si)) + { + return -1; + } + return si.nPos; +} + +/* + * Gets the range for the scrollbar in the scrollbox. + * Parameters: + * handle: Handle to the scrollbox to be queried. + * orient: The vertical or horizontal scrollbar. + */ +int API dw_scrollbox_get_range( HWND handle, int orient ) +{ + SCROLLINFO si; + int bar = SB_HORZ; + + if(orient == DW_VERT) + { + bar = SB_VERT; + } + + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_RANGE; + + /* Get the current scroll positions */ + if(!GetScrollInfo(handle, bar, &si)) + { + return -1; + } + return si.nMax; +} +/* + * Create a new Group Box to be packed. + * Parameters: + * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). + * pad: Number of pixels to pad around the box. + * title: Text to be displayined in the group outline. + */ +HWND API dw_groupbox_new(int type, int pad, char *title) +{ + Box *newbox = calloc(sizeof(Box), 1); + HWND hwndframe; + + newbox->pad = pad; + newbox->type = type; + newbox->count = 0; + newbox->cinfo.fore = newbox->cinfo.back = -1; + + hwndframe = CreateWindow(FRAMECLASSNAME, + "", + WS_VISIBLE | WS_CHILD, + 0,0,2000,1000, + DW_HWND_OBJECT, + NULL, + DWInstance, + NULL); + + newbox->grouphwnd = CreateWindow(BUTTONCLASSNAME, + title, + WS_CHILD | BS_GROUPBOX | + WS_VISIBLE | WS_CLIPCHILDREN, + 0,0,2000,1000, + hwndframe, + NULL, + DWInstance, + NULL); + + SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox); + dw_window_set_font(hwndframe, DefaultFont); + return hwndframe; +} + +/* + * Create a new MDI Frame to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id or 0L. + */ +HWND API dw_mdi_new(unsigned long id) +{ + CLIENTCREATESTRUCT ccs; + HWND hwndframe; + + ccs.hWindowMenu = NULL; + ccs.idFirstChild = 0; + + hwndframe = CreateWindow("MDICLIENT", + "", + WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + &ccs); + return hwndframe; +} + +/* + * Create a new HTML browser frame to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id or 0L. + */ +HWND API dw_html_new(unsigned long id) +{ +#if defined(BUILD_DLL) || defined(BUILD_HTML) + return CreateWindow(BrowserClassName, + "", + WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); +#else + return 0; +#endif +} + +/* + * Create a bitmap object to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id or 0L. + */ +HWND API dw_bitmap_new(ULONG id) +{ + return CreateWindow(STATICCLASSNAME, + "", + SS_BITMAP | SS_CENTERIMAGE | WS_VISIBLE | + WS_CHILD | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); +} + +/* + * Create a notebook object to be packed. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HWND API dw_notebook_new(ULONG id, int top) +{ + ULONG flags = 0; + HWND tmp; + NotebookPage **array = calloc(256, sizeof(NotebookPage *)); + + if(!top) + flags = TCS_BOTTOM; + + tmp = CreateWindow(WC_TABCONTROL, + "", + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | flags, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + dw_window_set_data(tmp, "_dw_array", (void *)array); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Create a menu object to be popped up. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HMENUI API dw_menu_new(ULONG id) +{ + return (HMENUI)CreatePopupMenu(); +} + +/* + * Create a menubar on a window. + * Parameters: + * location: Handle of a window frame to be attached to. + */ +HMENUI API dw_menubar_new(HWND location) +{ + HMENUI tmp; + MENUINFO mi; + + tmp = (HMENUI)CreateMenu(); + + mi.cbSize = sizeof(MENUINFO); + mi.fMask = MIM_MENUDATA; + mi.dwMenuData = (ULONG_PTR)1; + + SetMenuInfo( (HMENU)tmp, &mi ); + + dw_window_set_data(location, "_dw_menu", (void *)tmp); + + SetMenu(location, (HMENU)tmp); + return location; +} + +/* + * Destroys a menu created with dw_menubar_new or dw_menu_new. + * Parameters: + * menu: Handle of a menu. + */ +void API dw_menu_destroy(HMENUI *menu) +{ + if(menu) + { + HMENU mymenu = (HMENU)*menu; + + if(IsWindow((HWND)mymenu) && !IsMenu(mymenu)) + mymenu = (HMENU)dw_window_get_data((HWND)mymenu, "_dw_menu"); + if(IsMenu(mymenu)) + DestroyMenu(mymenu); + } +} + +/* Internal function to make sure menu ID isn't in use */ +int _menuid_allocated(int id) +{ + SignalHandler *tmp = Root; + + while(tmp) + { + if(tmp->id == id) + return TRUE; + tmp = tmp->next; + } + return FALSE; +} + +/* + * Adds a menuitem or submenu to an existing menu. + * Parameters: + * menu: The handle to the existing menu. + * title: The title text on the menu item to be added. + * id: An ID to be used for message passing. + * end: If TRUE memu is positioned at the end of the menu. + * check: If TRUE menu is "check"able. + * flags: Extended attributes to set on the menu. + * submenu: Handle to an existing menu to be a submenu or NULL. + */ +HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu) +{ + MENUITEMINFO mii; + HMENU mymenu = (HMENU)menux; + char buffer[31] = {0}; + int is_checked, is_disabled; + + /* + * Check if this is a menubar; if so get the menu object + * for the menubar + */ + if (IsWindow(menux) && !IsMenu(mymenu)) + mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu"); + + memset( &mii, 0, sizeof(mii) ); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_ID | MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE; + + /* Convert from OS/2 style accellerators to Win32 style */ + if (title) + { + char *tmp = title; + + while(*tmp) + { + if(*tmp == '~') + *tmp = '&'; + tmp++; + } + } + + if (title && *title) + { + /* Code to autogenerate a menu ID if not specified or invalid + * First pool is smaller for transient popup menus + */ + if(id == (ULONG)-1) + { + static ULONG tempid = 61000; + + tempid++; + id = tempid; + + if(tempid > 65500) + tempid = 61000; + } + /* Second pool is larger for more static windows */ + else if(!id || id >= 30000) + { + static ULONG menuid = 30000; + + do + { + menuid++; + if(menuid > 60000) + menuid = 30000; + } + while(_menuid_allocated(menuid)); + id = menuid; + } + mii.fType = MFT_STRING; + } + else + mii.fType = MFT_SEPARATOR; + + /* + * Handle flags + */ + is_checked = (flags & DW_MIS_CHECKED) ? 1 : 0; + if ( is_checked ) + mii.fState |= MFS_CHECKED; + else + mii.fState |= MFS_UNCHECKED; + is_disabled = (flags & DW_MIS_DISABLED) ? 1 : 0; + if ( is_disabled ) + mii.fState |= MFS_DISABLED; + else + mii.fState |= MFS_ENABLED; + + mii.wID = id; + if (IsMenu((HMENU)submenu)) + mii.hSubMenu = (HMENU)submenu; + else + mii.hSubMenu = 0; + mii.dwTypeData = title; + mii.cch = strlen(title); + + InsertMenuItem(mymenu, 65535, TRUE, &mii); + + _snprintf(buffer, 30, "_dw_id%ld", id); + dw_window_set_data( DW_HWND_OBJECT, buffer, (void *)mymenu ); + _snprintf(buffer, 30, "_dw_checkable%ld", id); + dw_window_set_data( DW_HWND_OBJECT, buffer, (void *)check ); + _snprintf(buffer, 30, "_dw_ischecked%ld", id); + dw_window_set_data( DW_HWND_OBJECT, buffer, (void *)is_checked ); + _snprintf(buffer, 30, "_dw_isdisabled%ld", id); + dw_window_set_data( DW_HWND_OBJECT, buffer, (void *)is_disabled ); + + if (submenu) + { + MENUINFO mi; + + mi.cbSize = sizeof(MENUINFO); + mi.fMask = MIM_MENUDATA; + mi.dwMenuData = (ULONG_PTR)mymenu; + + SetMenuInfo( (HMENU)submenu, &mi ); + } + + if (IsWindow(menux) && !IsMenu((HMENU)menux)) + DrawMenuBar(menux); + return (HWND)id; +} + +/* + * Sets the state of a menu item check. + * Deprecated: use dw_menu_item_set_state() + * Parameters: + * menu: The handle to the existing menu. + * id: Menuitem id. + * check: TRUE for checked FALSE for not checked. + */ +void API dw_menu_item_set_check(HMENUI menux, unsigned long id, int check) +{ + MENUITEMINFO mii; + HMENU mymenu = (HMENU)menux; + char buffer[30]; + + if (IsWindow(menux) && !IsMenu(mymenu)) + mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu"); + + /* + * Get the current state of the menu item in case it already has some other state set on it + */ + memset( &mii, 0, sizeof(mii) ); + GetMenuItemInfo( mymenu, id, FALSE, &mii); + + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE | MIIM_CHECKMARKS; + if (check) + mii.fState |= MFS_CHECKED; + else + mii.fState |= MFS_UNCHECKED; + SetMenuItemInfo( mymenu, id, FALSE, &mii ); + /* + * Keep our internal state consistent + */ + _snprintf( buffer, 30, "_dw_ischecked%ld", id ); + dw_window_set_data( DW_HWND_OBJECT, buffer, (void *)check ); +} + +/* + * Sets the state of a menu item. + * Parameters: + * menu: The handle to the existing menu. + * id: Menuitem id. + * flags: DW_MIS_ENABLED/DW_MIS_DISABLED + * DW_MIS_CHECKED/DW_MIS_UNCHECKED + */ +void API dw_menu_item_set_state( HMENUI menux, unsigned long id, unsigned long state) +{ + MENUITEMINFO mii; + HMENU mymenu = (HMENU)menux; + char buffer1[31] = {0},buffer2[31] = {0}; + int check; + int disabled; + + if (IsWindow(menux) && !IsMenu(mymenu)) + 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 ); + _snprintf( buffer2, 30, "_dw_isdisabled%ld", id ); + disabled = (int)dw_window_get_data( DW_HWND_OBJECT, buffer2 ); + + memset( &mii, 0, sizeof(mii) ); + + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE | MIIM_CHECKMARKS; + if ( (state & DW_MIS_CHECKED) || (state & DW_MIS_UNCHECKED) ) + { + /* + * If we are changing state of "checked" base our setting on the passed flag... + */ + if ( state & DW_MIS_CHECKED ) + { + mii.fState |= MFS_CHECKED; + check = 1; + } + else + { + mii.fState |= MFS_UNCHECKED; + check = 0; + } + } + else + { + /* + * ...otherwise base our setting on the current "checked" state. + */ + if ( check ) + { + mii.fState |= MFS_CHECKED; + } + else + { + mii.fState |= MFS_UNCHECKED; + } + } + if ( (state & DW_MIS_ENABLED) || (state & DW_MIS_DISABLED) ) + { + if ( state & DW_MIS_DISABLED ) + { + mii.fState |= MFS_DISABLED; + disabled = 1; + } + else + { + mii.fState |= MFS_ENABLED; + disabled = 0; + } + } + else + { + /* + * ...otherwise base our setting on the current "checked" state. + */ + if ( disabled ) + { + mii.fState |= MFS_DISABLED; + } + else + { + mii.fState |= MFS_ENABLED; + } + } + SetMenuItemInfo( mymenu, id, FALSE, &mii ); + /* + * 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 ); +} + +/* + * INCOMPLETE + * Deletes the menu item specified + * Parameters: + * menu: The handle to the menu in which the item was appended. + * id: Menuitem id. + */ +void API dw_menu_delete_item(HMENUI menux, unsigned long id) +{ + HMENU mymenu = (HMENU)menux; + + if ( IsWindow(menux) && !IsMenu(mymenu) ) + mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu"); + + if ( DeleteMenu(mymenu, id, MF_BYCOMMAND) == 0 ) + { + char lasterror[257]; + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), lasterror, 256, NULL); + fprintf(stderr, "Error deleting menu: %s", lasterror); + } + DrawMenuBar(menux); +} + +/* + * Pops up a context menu at given x and y coordinates. + * Parameters: + * menu: The handle the the existing menu. + * parent: Handle to the window initiating the popup. + * x: X coordinate. + * y: Y coordinate. + */ +void API dw_menu_popup(HMENUI *menu, HWND parent, int x, int y) +{ + if(menu) + { + HMENU mymenu = (HMENU)*menu; + + if(IsWindow(*menu) && !IsMenu(mymenu)) + mymenu = (HMENU)dw_window_get_data(*menu, "_dw_menu"); + + popup = parent; + TrackPopupMenu(mymenu, 0, x, y, 0, parent, NULL); + PostMessage(DW_HWND_OBJECT, WM_USER+5, (LPARAM)mymenu, 0); + } +} + + +/* + * Create a container object to be packed. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HWND API dw_container_new(ULONG id, int multi) +{ + HWND tmp = CreateWindow(WC_LISTVIEW, + "", + WS_VISIBLE | WS_CHILD | + (multi ? 0 : LVS_SINGLESEL) | + LVS_REPORT | LVS_SHOWSELALWAYS | + LVS_SHAREIMAGELISTS | WS_BORDER | + WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); + + if(!cinfo) + { + DestroyWindow(tmp); + return NULL; + } + + cinfo->cinfo.pOldProc = (WNDPROC)SubclassWindow(tmp, _containerwndproc); + cinfo->cinfo.fore = cinfo->cinfo.back = -1; + cinfo->odd = cinfo->even = DW_RGB_TRANSPARENT; + + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); + dw_window_set_font(tmp, DefaultFont); + /* If we are running XP or higher... */ + if(IS_XPPLUS) + { + /* Enable double buffering to prevent flicker */ + ListView_SetExtendedListViewStyleEx(tmp, LVS_EX_DOUBLEBUFFER, LVS_EX_DOUBLEBUFFER); + } + return tmp; +} + +/* + * Create a tree object to be packed. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HWND API dw_tree_new(ULONG id) +{ + HWND tmp = CreateWindow(WC_TREEVIEW, + "", + WS_VISIBLE | WS_CHILD | + TVS_HASLINES | TVS_SHOWSELALWAYS | + TVS_HASBUTTONS | TVS_LINESATROOT | + WS_BORDER | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); + TreeView_SetItemHeight(tmp, 16); + + if(!cinfo) + { + DestroyWindow(tmp); + return NULL; + } + + cinfo->cinfo.pOldProc = (WNDPROC)SubclassWindow(tmp, _treewndproc); + cinfo->cinfo.fore = cinfo->cinfo.back = -1; + cinfo->odd = cinfo->even = DW_RGB_TRANSPARENT; + + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Returns the current X and Y coordinates of the mouse pointer. + * Parameters: + * x: Pointer to variable to store X coordinate. + * y: Pointer to variable to store Y coordinate. + */ +void API dw_pointer_query_pos(long *x, long *y) +{ + POINT ptl; + + GetCursorPos(&ptl); + if(x && y) + { + *x = ptl.x; + *y = ptl.y; + } +} + +/* + * Sets the X and Y coordinates of the mouse pointer. + * Parameters: + * x: X coordinate. + * y: Y coordinate. + */ +void API dw_pointer_set_pos(long x, long y) +{ + SetCursorPos(x, y); +} + +/* + * Create a new static text window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_text_new(char *text, ULONG id) +{ + HWND tmp = CreateWindow(STATICCLASSNAME, + text, + SS_NOPREFIX | + BS_TEXT | WS_VISIBLE | + WS_CHILD | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Create a new status text window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_status_text_new(char *text, ULONG id) +{ + HWND tmp = CreateWindow(ObjectClassName, + text, + BS_TEXT | WS_VISIBLE | + WS_CHILD | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + dw_window_set_font(tmp, DefaultFont); + SubclassWindow(tmp, _statuswndproc); + return tmp; +} + +/* + * Create a new Multiline Editbox window (widget) to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_mle_new(ULONG id) +{ + + HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, + EDITCLASSNAME, + "", + WS_VISIBLE | WS_BORDER | + WS_VSCROLL | ES_MULTILINE | + ES_WANTRETURN | WS_CHILD | + WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); + + if(!cinfo) + { + DestroyWindow(tmp); + return NULL; + } + + cinfo->cinfo.pOldProc = (WNDPROC)SubclassWindow(tmp, _treewndproc); + cinfo->cinfo.fore = cinfo->cinfo.back = -1; + cinfo->odd = cinfo->even = DW_RGB_TRANSPARENT; + + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Create a new Entryfield window (widget) to be packed. + * Parameters: + * text: The default text to be in the entryfield widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_entryfield_new(char *text, ULONG id) +{ + HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, + EDITCLASSNAME, + text, + ES_WANTRETURN | WS_CHILD | + WS_BORDER | ES_AUTOHSCROLL | + WS_VISIBLE | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); + + cinfo->back = cinfo->fore = -1; + + cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc); + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Create a new Entryfield passwird window (widget) to be packed. + * Parameters: + * text: The default text to be in the entryfield widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_entryfield_password_new(char *text, ULONG id) +{ + HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, + EDITCLASSNAME, + text, + ES_WANTRETURN | WS_CHILD | + ES_PASSWORD | WS_BORDER | WS_VISIBLE | + ES_AUTOHSCROLL | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); + + cinfo->back = cinfo->fore = -1; + + cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc); + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +BOOL CALLBACK _subclass_child(HWND handle, LPARAM lp) +{ + ColorInfo *cinfo = (ColorInfo *)lp; + + if(cinfo) + { + cinfo->buddy = handle; + cinfo->pOldProc = (WNDPROC)SubclassWindow(handle, _colorwndproc); + SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo); + } + return FALSE; +} + +/* + * Create a new Combobox window (widget) to be packed. + * Parameters: + * text: The default text to be in the combpbox widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_combobox_new(char *text, ULONG id) +{ + HWND tmp = CreateWindow(COMBOBOXCLASSNAME, + text, + WS_CHILD | CBS_DROPDOWN | WS_VSCROLL | + WS_CLIPCHILDREN | CBS_AUTOHSCROLL | WS_VISIBLE, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + ColorInfo *cinfo = (ColorInfo *)calloc(1, sizeof(ColorInfo)); + ColorInfo *cinfo2 = (ColorInfo *)calloc(1, sizeof(ColorInfo)); + + if(!cinfo || !cinfo2) + { + if(cinfo) + free(cinfo); + if(cinfo2) + free(cinfo2); + DestroyWindow(tmp); + return NULL; + } + + cinfo2->fore = cinfo->fore = -1; + cinfo2->back = cinfo->back = -1; + cinfo2->combo = cinfo->combo = tmp; + EnumChildWindows(tmp, _subclass_child, (LPARAM)cinfo2); + + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); + dw_window_set_font(tmp, DefaultFont); + SetWindowText(tmp, text); + return tmp; +} + +/* + * Create a new button window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_button_new(char *text, ULONG id) +{ + BubbleButton *bubble = calloc(1, sizeof(BubbleButton)); + + HWND tmp = CreateWindow(BUTTONCLASSNAME, + text, + WS_CHILD | BS_PUSHBUTTON | + WS_VISIBLE | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + bubble->cinfo.fore = bubble->cinfo.back = -1; + bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); + + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Create a new bitmap button window (widget) to be packed. + * Parameters: + * text: Bubble help text to be displayed. + * id: An ID of a bitmap in the resource file. + */ +HWND API dw_bitmapbutton_new(char *text, ULONG id) +{ + HWND tmp; + BubbleButton *bubble = calloc(1, sizeof(BubbleButton)); + HBITMAP hbitmap = LoadBitmap(DWInstance, MAKEINTRESOURCE(id)); + HICON icon = LoadImage(DWInstance, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_SHARED); + + tmp = CreateWindow(BUTTONCLASSNAME, + "", + WS_CHILD | BS_PUSHBUTTON | + WS_VISIBLE | WS_CLIPCHILDREN | + (icon ? BS_ICON : BS_BITMAP), + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + + bubble->cinfo.fore = bubble->cinfo.back = -1; + bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); + + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble); + + _create_tooltip(tmp, text); + + if(icon) + { + SendMessage(tmp, BM_SETIMAGE, (WPARAM) IMAGE_ICON, (LPARAM) icon); + } + else if(hbitmap) + { + SendMessage(tmp, BM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) hbitmap); + } + return tmp; +} + +/* + * Create a new bitmap button window (widget) to be packed from a file. + * Parameters: + * text: Bubble help text to be displayed. + * id: An ID to be used with dw_window_from_id() or 0L. + * filename: Name of the file, omit extention to have + * DW pick the appropriate file extension. + * (BMP or ICO on OS/2 or Windows, XPM on Unix) + */ +HWND API dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename) +{ + HWND tmp; + BubbleButton *bubble; + HBITMAP hbitmap = 0; + HANDLE hicon = 0; + int windowtype = 0, len; + + if (!(bubble = calloc(1, sizeof(BubbleButton)))) + return 0; + +#ifdef GDIPLUS + if((hicon = _dw_load_icon(filename))) + windowtype = BS_ICON; + else + { + hbitmap = _dw_load_bitmap(filename, NULL); + windowtype = BS_BITMAP; + } +#else + windowtype = _dw_get_image_handle(filename, &hicon, &hbitmap); +#endif + + tmp = CreateWindow( BUTTONCLASSNAME, + "", + windowtype | WS_CHILD | BS_PUSHBUTTON | WS_CLIPCHILDREN | WS_VISIBLE, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + + bubble->cinfo.fore = bubble->cinfo.back = -1; + bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); + + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble); + + _create_tooltip(tmp, text); + + if (hicon) + { + SendMessage(tmp, BM_SETIMAGE,(WPARAM) IMAGE_ICON,(LPARAM) hicon); + } + else if (hbitmap) + { + SendMessage(tmp, BM_SETIMAGE,(WPARAM) IMAGE_BITMAP, (LPARAM) hbitmap); + } + return tmp; +} + +/* + * Create a new bitmap button window (widget) to be packed from data. + * Parameters: + * text: Bubble help text to be displayed. + * id: An ID to be used with dw_window_from_id() or 0L. + * data: The contents of the image + * (BMP or ICO on OS/2 or Windows, XPM on Unix) + * len: length of str + */ +HWND API dw_bitmapbutton_new_from_data(char *text, unsigned long id, char *data, int len) +{ + HWND tmp; + BubbleButton *bubble; + HBITMAP hbitmap = 0; + HANDLE hicon = 0; + char *file; + FILE *fp; + int windowtype; + + if ( !(bubble = calloc(1, sizeof(BubbleButton))) ) + return 0; + file = _tempnam( _dw_alternate_temp_dir, "dw" ); + if ( file != NULL ) + { + fp = fopen( file, "wb" ); + if ( fp != NULL ) + { + fwrite( data, 1, len, fp ); + fclose( fp ); +#ifdef GDIPLUS + if((hicon = _dw_load_icon(file))) + windowtype = BS_ICON; + else + { + hbitmap = _dw_load_bitmap(file, NULL); + windowtype = BS_BITMAP; + } +#else + if ( len > 1 && data[0] == 'B' && data[1] == 'M' ) /* first 2 chars of data is BM, then its a BMP */ + { + hbitmap = (HBITMAP)LoadImage( NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); + windowtype = BS_BITMAP; + } + else /* otherwise its assumed to be an ico */ + { + hicon = LoadImage( NULL, file, IMAGE_ICON, 0, 0, LR_LOADFROMFILE ); + windowtype = BS_ICON; + } +#endif + } + else + { + unlink( file ); + free( file ); + return 0; + } + unlink( file ); + free( file ); + } + + tmp = CreateWindow( BUTTONCLASSNAME, + "", + WS_CHILD | BS_PUSHBUTTON | + windowtype | WS_CLIPCHILDREN | + WS_VISIBLE, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL ); + + bubble->cinfo.fore = bubble->cinfo.back = -1; + bubble->pOldProc = (WNDPROC)SubclassWindow( tmp, _BtProc ); + + SetWindowLongPtr( tmp, GWLP_USERDATA, (LONG_PTR)bubble ); + + _create_tooltip(tmp, text); + + if ( hicon ) + { + SendMessage( tmp, BM_SETIMAGE, (WPARAM) IMAGE_ICON, (LPARAM) hicon); + } + else if( hbitmap ) + { + SendMessage( tmp, BM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) hbitmap); + } + return tmp; +} + +/* + * Create a new spinbutton window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_spinbutton_new(char *text, ULONG id) +{ + HWND buddy = CreateWindowEx(WS_EX_CLIENTEDGE, + EDITCLASSNAME, + text, + WS_CHILD | WS_BORDER | WS_VISIBLE | + ES_NUMBER | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + NULL, + DWInstance, + NULL); + HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, + UPDOWN_CLASS, + NULL, + WS_CHILD | UDS_ALIGNRIGHT | WS_BORDER | + UDS_ARROWKEYS | UDS_SETBUDDYINT | + UDS_WRAP | UDS_NOTHOUSANDS | WS_VISIBLE, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); + + SendMessage(tmp, UDM_SETRANGE32, (WPARAM)-65536,(LPARAM)65536); + SendMessage(tmp, UDM_SETBUDDY, (WPARAM)buddy, 0); + cinfo->back = cinfo->fore = -1; + cinfo->buddy = tmp; + + cinfo->pOldProc = SubclassWindow(buddy, _colorwndproc); + SetWindowLongPtr(buddy, GWLP_USERDATA, (LONG_PTR)cinfo); + + cinfo = calloc(1, sizeof(ColorInfo)); + cinfo->buddy = buddy; + /* The horrible spinbutton workaround isn't necessary + * any more on Vista or 7... but still seems necessary + * for XP, so only enable it if on XP or lower. + */ + if(!IS_VISTAPLUS) + { + cinfo->pOldProc = SubclassWindow(tmp, _spinnerwndproc); + } + + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); + dw_window_set_font(buddy, DefaultFont); + return tmp; +} + +/* + * Create a new radiobutton window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_radiobutton_new(char *text, ULONG id) +{ + HWND tmp = CreateWindow(BUTTONCLASSNAME, + text, + WS_CHILD | BS_AUTORADIOBUTTON | + WS_CLIPCHILDREN | WS_VISIBLE, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + BubbleButton *bubble = calloc(1, sizeof(BubbleButton)); + bubble->cinfo.fore = bubble->cinfo.back = -1; + bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + + +/* + * Create a new slider window (widget) to be packed. + * Parameters: + * vertical: TRUE or FALSE if slider is vertical. + * increments: Number of increments available. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_slider_new(int vertical, int increments, ULONG id) +{ + HWND tmp = CreateWindow(TRACKBAR_CLASS, + "", + WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | + (vertical ? TBS_VERT : TBS_HORZ), + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); + + cinfo->back = cinfo->fore = -1; + + cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc); + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); + SendMessage(tmp, TBM_SETRANGE, (WPARAM)FALSE, (LPARAM)MAKELONG(0, increments-1)); + return tmp; +} + +/* + * Create a new scrollbar window (widget) to be packed. + * Parameters: + * vertical: TRUE or FALSE if scrollbar is vertical. + * increments: Number of increments available. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_scrollbar_new(int vertical, ULONG id) +{ + HWND tmp = CreateWindow(SCROLLBARCLASSNAME, + "", + WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | + (vertical ? SBS_VERT : SBS_HORZ), + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + ColorInfo *cinfo = calloc(1, sizeof(ColorInfo)); + + cinfo->back = cinfo->fore = -1; + + cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc); + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); + dw_window_set_data(tmp, "_dw_scrollbar", (void *)1); + return tmp; +} + +/* + * Create a new percent bar window (widget) to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_percent_new(ULONG id) +{ + return CreateWindow(PROGRESS_CLASS, + "", + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); +} + +/* + * Create a new checkbox window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with dw_window_from_id() or 0L. + */ +HWND API dw_checkbox_new(char *text, ULONG id) +{ + BubbleButton *bubble = calloc(1, sizeof(BubbleButton)); + HWND tmp = CreateWindow(BUTTONCLASSNAME, + text, + WS_CHILD | BS_AUTOCHECKBOX | + BS_TEXT | WS_CLIPCHILDREN | WS_VISIBLE, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + bubble->checkbox = 1; + bubble->cinfo.fore = bubble->cinfo.back = -1; + bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc); + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Create a new listbox window (widget) to be packed. + * Parameters: + * id: An ID to be used with dw_window_from_id() or 0L. + * multi: Multiple select TRUE or FALSE. + */ +HWND API dw_listbox_new(ULONG id, int multi) +{ + HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, + LISTBOXCLASSNAME, + "", + WS_VISIBLE | LBS_NOINTEGRALHEIGHT | + WS_CHILD | LBS_HASSTRINGS | + LBS_NOTIFY | WS_BORDER | WS_CLIPCHILDREN | + WS_VSCROLL | (multi ? LBS_MULTIPLESEL : 0) , + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo)); + + if(!cinfo) + { + DestroyWindow(tmp); + return NULL; + } + + cinfo->cinfo.fore = cinfo->cinfo.back = -1; + cinfo->odd = cinfo->even = DW_RGB_TRANSPARENT; + cinfo->cinfo.pOldProc = (WNDPROC)SubclassWindow(tmp, _containerwndproc); + + SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo); + dw_window_set_font(tmp, DefaultFont); + return tmp; +} + +/* + * Sets the icon used for a given window. + * Parameters: + * handle: Handle to the window. + * id: An ID to be used to specify the icon. + */ +void API dw_window_set_icon(HWND handle, HICN icon) +{ + int iicon = (int)icon; + HICON hicon = iicon < 65536 ? LoadIcon(DWInstance, MAKEINTRESOURCE(iicon)) : (HICON)icon; + + SendMessage(handle, WM_SETICON, + (WPARAM) IMAGE_ICON, + (LPARAM) hicon); +} + +/* + * Sets the bitmap used for a given static window. + * Parameters: + * handle: Handle to the window. + * id: An ID to be used to specify the icon, + * (pass 0 if you use the filename param) + * filename: a path to a file (Bitmap on OS/2 or + * Windows and a pixmap on Unix, pass + * NULL if you use the id param) + */ +void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename) +{ + HBITMAP hbitmap; + HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, STM_GETIMAGE, IMAGE_BITMAP, 0); + HICON icon = 0; + HICON oldicon = (HICON)SendMessage(handle, STM_GETIMAGE, IMAGE_ICON, 0); + + if(id) + { + hbitmap = LoadImage(DWInstance, MAKEINTRESOURCE(id), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS | LR_SHARED); + icon = LoadImage(DWInstance, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_SHARED); + } + else if(filename) + { +#ifdef GDIPLUS + hbitmap = _dw_load_bitmap(filename, NULL); +#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); +} + +/* + * Sets the bitmap used for a given static window from data. + * Parameters: + * handle: Handle to the window. + * id: An ID to be used to specify the icon, + * (pass 0 if you use the data param) + * data: the image from meory + * Bitmap on Windows and a pixmap on Unix, pass + * NULL if you use the id param) + * len: length of data + */ +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; + + if ( id ) + { + hbitmap = LoadBitmap( DWInstance, MAKEINTRESOURCE(id) ); + icon = LoadImage( DWInstance, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_SHARED ); + } + else if (data) + { + file = _tempnam( _dw_alternate_temp_dir, "dw" ); + if ( file != NULL ) + { + fp = fopen( file, "wb" ); + if ( fp != NULL ) + { + fwrite( data, 1, len, fp ); + fclose( fp ); +#ifdef GDIPLUS + hbitmap = _dw_load_bitmap(file, NULL); +#else + if ( len > 1 && data[0] == 'B' && data[1] == 'M' ) /* first 2 chars of data is BM, then its a BMP */ + hbitmap = (HBITMAP)LoadImage( NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); + else /* otherwise its assumed to be an ico */ + icon = LoadImage( NULL, file, IMAGE_ICON, 0, 0, LR_LOADFROMFILE ); +#endif + } + else + { + unlink( file ); + free( file ); + return; + } + unlink( file ); + free( file ); + } + 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 ); +} + + +/* + * Sets the text used for a given window. + * Parameters: + * handle: Handle to the window. + * text: The text associsated with a given window. + */ +void API dw_window_set_text(HWND handle, char *text) +{ + Box *thisbox; + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + SetWindowText(handle, text); + + /* Combobox */ + if ( strnicmp( tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1) == 0 ) + SendMessage(handle, CB_SETEDITSEL, 0, MAKELPARAM(-1, 0)); + else if ( strnicmp( tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1) == 0 ) + { + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + if( cinfo && cinfo->buddy ) + SetWindowText( cinfo->buddy, text ); + } + else if ( strnicmp( tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1) == 0 ) + { + /* groupbox */ + thisbox = (Box *)GetWindowLongPtr( handle, GWLP_USERDATA ); + if ( thisbox && thisbox->grouphwnd != (HWND)NULL ) + SetWindowText( thisbox->grouphwnd, text ); + } +} + +/* + * Gets the text used for a given window. + * Parameters: + * handle: Handle to the window. + * Returns: + * text: The text associsated with a given window. + */ +char * API dw_window_get_text(HWND handle) +{ + char tmpbuf[100], *tempbuf; + int len; + + GetClassName(handle, tmpbuf, 99); + + if ( strnicmp( tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1) == 0 ) + { + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + + if( cinfo && cinfo->buddy ) + handle = cinfo->buddy; + else + return NULL; + } + + len = GetWindowTextLength(handle); + tempbuf = calloc(1, len + 2); + + GetWindowText(handle, tempbuf, len + 1); + + return tempbuf; +} + +/* + * Disables given window (widget). + * Parameters: + * handle: Handle to the window. + */ +void API dw_window_disable(HWND handle) +{ + if(handle < (HWND)65536) + { + char buffer[31] = {0}; + HMENU mymenu; + ULONG id = (ULONG)handle; + + _snprintf(buffer, 30, "_dw_id%ld", id); + mymenu = (HMENU)dw_window_get_data(DW_HWND_OBJECT, buffer); + + if(mymenu && IsMenu(mymenu)) + dw_menu_item_set_state((HMENUI)mymenu, id, DW_MIS_DISABLED); + } + else + EnableWindow(handle, FALSE); +} + +/* + * Enables given window (widget). + * Parameters: + * handle: Handle to the window. + */ +void API dw_window_enable(HWND handle) +{ + if(handle < (HWND)65536) + { + char buffer[31] = {0}; + HMENU mymenu; + ULONG id = (ULONG)handle; + + _snprintf(buffer, 30, "_dw_id%ld", id); + mymenu = (HMENU)dw_window_get_data(DW_HWND_OBJECT, buffer); + + if(mymenu && IsMenu(mymenu)) + dw_menu_item_set_state((HMENUI)mymenu, id, DW_MIS_ENABLED); + } + else + EnableWindow(handle, TRUE); +} + +static HWND _dw_wfid_hwnd = NULL; + +BOOL CALLBACK _wfid(HWND handle, LPARAM lParam) +{ + if(GetWindowLong(handle, GWL_ID) == lParam) + { + _dw_wfid_hwnd = handle; + return FALSE; + } + return TRUE; +} + +/* + * Gets the child window handle with specified ID. + * Parameters: + * handle: Handle to the parent window. + * id: Integer ID of the child. + */ +HWND API dw_window_from_id(HWND handle, int id) +{ + _dw_wfid_hwnd = NULL; + EnumChildWindows(handle, _wfid, (LPARAM)id); + return _dw_wfid_hwnd; +} + +/* Internal box packing function called by the other 3 functions */ +void _dw_box_pack(HWND box, HWND item, int index, int width, int height, int hsize, int vsize, int pad, char *funcname) +{ + Box *thisbox = NULL; + char tmpbuf[100]; + + /* + * If you try and pack an item into itself VERY bad things can happen; like at least an + * infinite loop on GTK! Lets be safe! + */ + if(box == item) + { + dw_messagebox(funcname, DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!"); + return; + } + + GetClassName(box, tmpbuf, 99); + + /* If we are in a scrolled box... extract the interal box */ + if(strnicmp(tmpbuf, ScrollClassName, strlen(ScrollClassName)+1)==0) + { + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(box, GWLP_USERDATA); + if(cinfo) + { + box = cinfo->buddy; + thisbox = (Box *)GetWindowLongPtr(box, GWLP_USERDATA); + } + } + else //if(strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1)==0) + thisbox = (Box *)GetWindowLongPtr(box, GWLP_USERDATA); + if(thisbox) + { + int z, x = 0; + Item *tmpitem, *thisitem = thisbox->items; + + /* Do some sanity bounds checking */ + if(index < 0) + index = 0; + if(index > thisbox->count) + index = thisbox->count; + + tmpitem = malloc(sizeof(Item)*(thisbox->count+1)); + + for(z=0;z<thisbox->count;z++) + { + if(z == index) + x++; + tmpitem[x] = thisitem[z]; + x++; + } + + GetClassName(item, tmpbuf, 99); + + if(vsize && !height) + height = 1; + if(hsize && !width) + width = 1; + + if(strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1)==0) + tmpitem[index].type = TYPEBOX; + else if(strnicmp(tmpbuf, "SysMonthCal32", 13)==0) + { + RECT rc; + MonthCal_GetMinReqRect(item, &rc); + width = 1 + rc.right - rc.left; + height = 1 + rc.bottom - rc.top; + tmpitem[index].type = TYPEITEM; + } + else + { + if ( width == 0 && hsize == FALSE ) + dw_messagebox(funcname, DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item); + if ( height == 0 && vsize == FALSE ) + dw_messagebox(funcname, DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item); + + tmpitem[index].type = TYPEITEM; + } + + tmpitem[index].hwnd = item; + tmpitem[index].origwidth = tmpitem[index].width = width; + tmpitem[index].origheight = tmpitem[index].height = height; + tmpitem[index].pad = pad; + if(hsize) + tmpitem[index].hsize = SIZEEXPAND; + else + tmpitem[index].hsize = SIZESTATIC; + + if(vsize) + tmpitem[index].vsize = SIZEEXPAND; + else + tmpitem[index].vsize = SIZESTATIC; + + thisbox->items = tmpitem; + + if(thisbox->count) + free(thisitem); + + thisbox->count++; + + SetParent(item, box); + if(strncmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0) + { + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(item, GWLP_USERDATA); + + if(cinfo) + { + SetParent(cinfo->buddy, box); + ShowWindow(cinfo->buddy, SW_SHOW); + SendMessage(item, UDM_SETBUDDY, (WPARAM)cinfo->buddy, 0); + } + } + } +} + +/* + * Pack windows (widgets) into a box at an arbitrary location. + * Parameters: + * box: Window handle of the box to be packed into. + * item: Window handle of the item to be back. + * index: 0 based index of packed items. + * width: Width in pixels of the item or -1 to be self determined. + * height: Height in pixels of the item or -1 to be self determined. + * hsize: TRUE if the window (widget) should expand horizontally to fill space given. + * vsize: TRUE if the window (widget) should expand vertically to fill space given. + * pad: Number of pixels of padding around the item. + */ +void API dw_box_pack_at_index(HWND box, HWND item, int index, int width, int height, int hsize, int vsize, int pad) +{ + _dw_box_pack(box, item, index, width, height, hsize, vsize, pad, "dw_box_pack_at_index()"); +} + +/* + * Pack windows (widgets) into a box from the start (or top). + * Parameters: + * box: Window handle of the box to be packed into. + * item: Window handle of the item to be back. + * width: Width in pixels of the item or -1 to be self determined. + * height: Height in pixels of the item or -1 to be self determined. + * hsize: TRUE if the window (widget) should expand horizontally to fill space given. + * vsize: TRUE if the window (widget) should expand vertically to fill space given. + * pad: Number of pixels of padding around the item. + */ +void API dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) +{ + /* 65536 is the table limit on GTK... + * seems like a high enough value we will never hit it here either. + */ + _dw_box_pack(box, item, 65536, width, height, hsize, vsize, pad, "dw_box_pack_start()"); +} + +/* + * Pack windows (widgets) into a box from the end (or bottom). + * Parameters: + * box: Window handle of the box to be packed into. + * item: Window handle of the item to be back. + * width: Width in pixels of the item or -1 to be self determined. + * height: Height in pixels of the item or -1 to be self determined. + * hsize: TRUE if the window (widget) should expand horizontally to fill space given. + * vsize: TRUE if the window (widget) should expand vertically to fill space given. + * pad: Number of pixels of padding around the item. + */ +void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) +{ + _dw_box_pack(box, item, 0, width, height, hsize, vsize, pad, "dw_box_pack_end()"); +} + +/* + * Sets the size of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * width: New width in pixels. + * height: New height in pixels. + */ +void API dw_window_set_size(HWND handle, ULONG width, ULONG height) +{ + int usedx = 0, usedy = 0, depth = 0, usedpadx = 0, usedpady = 0; + Box *thisbox; + /* + * The following is an attempt to dynamically size a window based on the size of its + * children before realization. Only applicable when width or height is zero. + * It doesn't work vey well :-( + */ + thisbox = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA); + if ( thisbox ) + { + _resize_box(thisbox, &depth, 0, 0, &usedx, &usedy, 1, &usedpadx, &usedpady); + _resize_box(thisbox, &depth, usedx, usedy, &usedx, &usedy, 2, &usedpadx, &usedpady); + } + if ( width == 0 ) width = usedx; + if ( height == 0 ) height = usedy; + SetWindowPos(handle, (HWND)NULL, 0, 0, width, height, SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOMOVE); +} + +/* + * Returns the width of the screen. + */ +int API dw_screen_width(void) +{ + return screenx; +} + +/* + * Returns the height of the screen. + */ +int API dw_screen_height(void) +{ + return screeny; +} + +/* This should return the current color depth */ +unsigned long API dw_color_depth_get(void) +{ + int bpp; + HDC hdc = GetDC(HWND_DESKTOP); + + bpp = GetDeviceCaps(hdc, BITSPIXEL); + + ReleaseDC(HWND_DESKTOP, hdc); + + return bpp; +} + + +/* + * Sets the position of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * x: X location from the bottom left. + * y: Y location from the bottom left. + */ +void API dw_window_set_pos(HWND handle, long x, long y) +{ + SetWindowPos(handle, (HWND)NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); +} + +/* + * Sets the position and size of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * x: X location from the bottom left. + * y: Y location from the bottom left. + * width: Width of the widget. + * height: Height of the widget. + */ +void API dw_window_set_pos_size(HWND handle, long x, long y, ULONG width, ULONG height) +{ + int usedx = 0, usedy = 0, depth = 0, usedpadx = 0, usedpady = 0; + Box *thisbox; + /* + * The following is an attempt to dynamically size a window based on the size of its + * children before realization. Only applicable when width or height is zero. + * It doesn't work vey well :-( + */ + thisbox = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA); + if ( thisbox ) + { + _resize_box(thisbox, &depth, 0, 0, &usedx, &usedy, 1, &usedpadx, &usedpady); + _resize_box(thisbox, &depth, usedx, usedy, &usedx, &usedy, 2, &usedpadx, &usedpady); + } + if ( width == 0 ) width = usedx; + if ( height == 0 ) height = usedy; + SetWindowPos(handle, (HWND)NULL, x, y, width, height, SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE); +#if 0 + /* force a configure event */ + SendMessage( handle, WM_SIZE, 0, MAKELPARAM(width, height) ); +#endif +} + +/* + * Gets the position and size of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * x: X location from the bottom left. + * y: Y location from the bottom left. + * width: Width of the widget. + * height: Height of the widget. + */ +void API dw_window_get_pos_size(HWND handle, long *x, long *y, ULONG *width, ULONG *height) +{ + WINDOWPLACEMENT wp; + + wp.length = sizeof(WINDOWPLACEMENT); + + GetWindowPlacement(handle, &wp); + if( wp.showCmd == SW_SHOWMAXIMIZED) + { + if(x) + *x=0; + if(y) + *y=0; + if(width) + *width=dw_screen_width(); + if(height) + *height=dw_screen_height(); + } + else + { + if(x) + *x = wp.rcNormalPosition.left; + if(y) + *y = wp.rcNormalPosition.top; + if(width) + *width = wp.rcNormalPosition.right - wp.rcNormalPosition.left; + if(height) + *height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; + } +} + +/* + * Sets the style of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * width: New width in pixels. + * height: New height in pixels. + */ +void API dw_window_set_style(HWND handle, ULONG style, ULONG mask) +{ + ULONG tmp, currentstyle; + ColorInfo *cinfo; + + if(handle < (HWND)65536) + { + char buffer[31] = {0}; + HMENU mymenu; + ULONG id = (ULONG)handle; + + _snprintf(buffer, 30, "_dw_id%ld", id); + mymenu = (HMENU)dw_window_get_data(DW_HWND_OBJECT, buffer); + + if(mymenu && IsMenu(mymenu)) + dw_menu_item_set_state((HMENUI)mymenu, id, style & mask); + return; + } + + currentstyle = GetWindowLong(handle, GWL_STYLE); + cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + + tmp = currentstyle | mask; + tmp ^= mask; + tmp |= style; + + /* We are using SS_NOPREFIX as a VCENTER flag */ + if(tmp & SS_NOPREFIX) + { + + if(cinfo) + cinfo->vcenter = 1; + else + { + cinfo = calloc(1, sizeof(ColorInfo)); + cinfo->fore = cinfo->back = -1; + cinfo->vcenter = 1; + + cinfo->pOldProc = SubclassWindow(handle, _colorwndproc); + SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo); + } + } + else if(cinfo) + cinfo->vcenter = 0; + + SetWindowLong(handle, GWL_STYLE, tmp); +} + +/* Finds the physical ID from the reference ID */ +int _findnotebookid(NotebookPage **array, int pageid) +{ + int z; + + for(z=0;z<256;z++) + { + if(array[z] && array[z]->realid == pageid) + return z; + } + return -1; +} + +/* + * Adds a new page to specified notebook. + * Parameters: + * handle: Window (widget) handle. + * flags: Any additional page creation flags. + * front: If TRUE page is added at the beginning. + */ +unsigned long API dw_notebook_page_new(HWND handle, ULONG flags, int front) +{ + NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); + + if(array) + { + int z, refid = -1; + + for(z=0;z<256;z++) + { + if(_findnotebookid(array, z) == -1) + { + refid = z; + break; + } + } + + if(refid == -1) + return -1; + + for(z=0;z<256;z++) + { + if(!array[z]) + { + int oldpage = TabCtrl_GetCurSel(handle); + + array[z] = calloc(1, sizeof(NotebookPage)); + array[z]->realid = refid; + array[z]->item.mask = TCIF_TEXT; + array[z]->item.iImage = -1; + array[z]->item.pszText = ""; + TabCtrl_InsertItem(handle, z, &(array[z]->item)); + return refid; + } + } + } + return -1; +} + +/* + * Sets the text on the specified notebook tab. + * Parameters: + * handle: Notebook handle. + * pageid: Page ID of the tab to set. + * text: Pointer to the text to set. + */ +void API dw_notebook_page_set_text(HWND handle, ULONG pageidx, char *text) +{ + + NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); + int pageid; + + if(!array) + return; + + pageid = _findnotebookid(array, pageidx); + + if(pageid > -1 && array[pageid]) + { + array[pageid]->item.mask = TCIF_TEXT; + array[pageid]->item.pszText = text; + TabCtrl_SetItem(handle, pageid, &(array[pageid]->item)); + _resize_notebook_page(handle, pageid); + } +} + +/* + * Sets the text on the specified notebook tab status area. + * Parameters: + * handle: Notebook handle. + * pageid: Page ID of the tab to set. + * text: Pointer to the text to set. + */ +void API dw_notebook_page_set_status_text(HWND handle, ULONG pageid, char *text) +{ +} + +/* + * Packs the specified box into the notebook page. + * Parameters: + * handle: Handle to the notebook to be packed. + * pageid: Page ID in the notebook which is being packed. + * page: Box handle to be packed. + */ +void API dw_notebook_pack(HWND handle, ULONG pageidx, HWND page) +{ + NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); + int pageid; + + if(!array) + return; + + pageid = _findnotebookid(array, pageidx); + + if(pageid > -1 && array[pageid]) + { + HWND tmpbox = dw_box_new(DW_VERT, 0); + + dw_box_pack_start(tmpbox, page, 0, 0, TRUE, TRUE, 0); + SubclassWindow(tmpbox, _wndproc); + if(array[pageid]->hwnd) + dw_window_destroy(array[pageid]->hwnd); + array[pageid]->hwnd = tmpbox; + if(pageidx == dw_notebook_page_get(handle)) + { + ShowWindow(tmpbox, SW_HIDE); + SetParent(tmpbox, handle); + _resize_notebook_page(handle, pageid); + } + } +} + +/* + * Remove a page from a notebook. + * Parameters: + * handle: Handle to the notebook widget. + * pageid: ID of the page to be destroyed. + */ +void API dw_notebook_page_destroy(HWND handle, unsigned int pageidx) +{ + NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); + int newid = -1, z, pageid; + HWND pagehwnd = 0; + + if(!array) + return; + + pageid = _findnotebookid(array, pageidx); + + if(pageid < 0) + return; + + if(array[pageid]) + { + SetParent(array[pageid]->hwnd, DW_HWND_OBJECT); + pagehwnd = array[pageid]->hwnd; + free(array[pageid]); + array[pageid] = NULL; + } + + TabCtrl_DeleteItem(handle, pageid); + + /* Shift the pages over 1 */ + for(z=pageid;z<255;z++) + array[z] = array[z+1]; + array[255] = NULL; + + for(z=0;z<256;z++) + { + if(array[z]) + { + newid = z; + break; + } + } + if(newid > -1) + { + SetParent(array[newid]->hwnd, handle); + _resize_notebook_page(handle, newid); + dw_notebook_page_set(handle, array[newid]->realid); + } + if(pagehwnd) + dw_window_destroy(pagehwnd); +} + +/* + * Queries the currently visible page ID. + * Parameters: + * handle: Handle to the notebook widget. + */ +unsigned long API dw_notebook_page_get(HWND handle) +{ + NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); + int physid = TabCtrl_GetCurSel(handle); + + if(physid > -1 && physid < 256 && array && array[physid]) + return array[physid]->realid; + return -1; +} + +/* + * Sets the currently visible page ID. + * Parameters: + * handle: Handle to the notebook widget. + * pageid: ID of the page to be made visible. + */ +void API dw_notebook_page_set(HWND handle, unsigned int pageidx) +{ + NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array"); + int pageid; + + if(!array) + return; + + pageid = _findnotebookid(array, pageidx); + + if(pageid > -1 && pageid < 256) + { + int oldpage = TabCtrl_GetCurSel(handle); + + if(oldpage > -1 && array && array[oldpage]) + SetParent(array[oldpage]->hwnd, DW_HWND_OBJECT); + + TabCtrl_SetCurSel(handle, pageid); + + SetParent(array[pageid]->hwnd, handle); + _resize_notebook_page(handle, pageid); + } +} + +/* + * Appends the specified text to the listbox's (or combobox) entry list. + * Parameters: + * handle: Handle to the listbox to be appended to. + * text: Text to append into listbox. + */ +void API dw_listbox_append(HWND handle, char *text) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + SendMessage(handle, + CB_ADDSTRING, + 0, (LPARAM)text); + else + SendMessage(handle, + LB_ADDSTRING, + 0, (LPARAM)text); +} + +/* + * Appends the specified text items to the listbox's (or combobox) entry list. + * Parameters: + * handle: Handle to the listbox to be appended to. + * text: Text strings to append into listbox. + * count: Number of text strings to append + */ +void API dw_listbox_list_append(HWND handle, char **text, int count) +{ + char tmpbuf[100]; + int listbox_type; + int i; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + listbox_type = CB_ADDSTRING; + else + listbox_type = LB_ADDSTRING; + + for(i=0;i<count;i++) + SendMessage(handle,(WPARAM)listbox_type,0,(LPARAM)text[i]); +} + +/* + * Inserts the specified text to the listbox's (or combobox) entry list. + * Parameters: + * handle: Handle to the listbox to be appended to. + * text: Text to append into listbox. + * pos: 0 based position to insert text + */ +void API dw_listbox_insert(HWND handle, char *text, int pos) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + SendMessage(handle, + CB_INSERTSTRING, + pos, (LPARAM)text); + else + SendMessage(handle, + LB_INSERTSTRING, + pos, (LPARAM)text); +} + +/* + * Clears the listbox's (or combobox) list of all entries. + * Parameters: + * handle: Handle to the listbox to be cleared. + */ +void API dw_listbox_clear(HWND handle) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + { + char *buf = dw_window_get_text(handle); + + SendMessage(handle, + CB_RESETCONTENT, 0L, 0L); + + if(buf) + { + dw_window_set_text(handle, buf); + free(buf); + } + } + else + SendMessage(handle, + LB_RESETCONTENT, 0L, 0L); +} + +/* + * Sets the text of a given listbox entry. + * Parameters: + * handle: Handle to the listbox to be queried. + * index: Index into the list to be queried. + * buffer: Buffer where text will be copied. + */ +void API dw_listbox_set_text(HWND handle, unsigned int index, char *buffer) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + { + SendMessage(handle, CB_DELETESTRING, (WPARAM)index, 0); + SendMessage(handle, CB_INSERTSTRING, (WPARAM)index, (LPARAM)buffer); + } + else + { + unsigned int sel = (unsigned int)SendMessage(handle, LB_GETCURSEL, 0, 0); + SendMessage(handle, LB_DELETESTRING, (WPARAM)index, 0); + SendMessage(handle, LB_INSERTSTRING, (WPARAM)index, (LPARAM)buffer); + SendMessage(handle, LB_SETCURSEL, (WPARAM)sel, 0); + SendMessage(handle, LB_SETSEL, (WPARAM)TRUE, (LPARAM)sel); + } +} + +/* + * Copies the given index item's text into buffer. + * Parameters: + * handle: Handle to the listbox to be queried. + * index: Index into the list to be queried. + * buffer: Buffer where text will be copied. + * length: Length of the buffer (including NULL). + */ +void API dw_listbox_get_text(HWND handle, unsigned int index, char *buffer, unsigned int length) +{ + char tmpbuf[100]; + int len; + + if(!buffer || !length) + return; + + buffer[0] = 0; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + { + len = (int)SendMessage(handle, CB_GETLBTEXTLEN, (WPARAM)index, 0); + + if(len < length && len != CB_ERR) + SendMessage(handle, + CB_GETLBTEXT, (WPARAM)index, (LPARAM)buffer); + } + else + { + len = (int)SendMessage(handle, LB_GETTEXTLEN, (WPARAM)index, 0); + + if(len < length && len != LB_ERR) + SendMessage(handle, + LB_GETTEXT, (WPARAM)index, (LPARAM)buffer); + } +} + +/* + * Returns the index to the item in the list currently selected. + * Parameters: + * handle: Handle to the listbox to be queried. + */ +int API dw_listbox_selected(HWND handle) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + return (unsigned int)SendMessage(handle, + CB_GETCURSEL, + 0, 0); + + return (unsigned int)SendMessage(handle, + LB_GETCURSEL, + 0, 0); +} + +/* + * Returns the index to the current selected item or -1 when done. + * Parameters: + * handle: Handle to the listbox to be queried. + * where: Either the previous return or -1 to restart. + */ +int API dw_listbox_selected_multi(HWND handle, int where) +{ + int *array, count, z; + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + /* This doesn't work on comboboxes */ + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + return -1; + + count = (int)SendMessage(handle, LB_GETSELCOUNT, 0, 0); + if(count > 0) + { + array = malloc(sizeof(int)*count); + SendMessage(handle, LB_GETSELITEMS, (WPARAM)count, (LPARAM)array); + + if(where == -1) + { + int ret = array[0]; + free(array); + return ret; + } + for(z=0;z<count;z++) + { + if(array[z] == where && (z+1) < count) + { + int ret = array[z+1]; + free(array); + return ret; + } + } + free(array); + } + return -1; +} + +/* + * Sets the selection state of a given index. + * Parameters: + * handle: Handle to the listbox to be set. + * index: Item index. + * state: TRUE if selected FALSE if unselected. + */ +void API dw_listbox_select(HWND handle, int index, int state) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + SendMessage(handle, CB_SETCURSEL, (WPARAM)index, 0); + else + { + SendMessage(handle, LB_SETCURSEL, (WPARAM)index, 0); + SendMessage(handle, LB_SETSEL, (WPARAM)state, (LPARAM)index); + } + _wndproc(handle, WM_COMMAND, (WPARAM)(LBN_SELCHANGE << 16), (LPARAM)handle); +} + +/* + * Deletes the item with given index from the list. + * Parameters: + * handle: Handle to the listbox to be set. + * index: Item index. + */ +void API dw_listbox_delete(HWND handle, int index) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + SendMessage(handle, CB_DELETESTRING, (WPARAM)index, 0); + else + SendMessage(handle, LB_DELETESTRING, (WPARAM)index, 0); +} + +/* + * Returns the listbox's item count. + * Parameters: + * handle: Handle to the listbox to be cleared. + */ +int API dw_listbox_count(HWND handle) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + return (int)SendMessage(handle, + CB_GETCOUNT,0L, 0L); + + return (int)SendMessage(handle, + LB_GETCOUNT,0L, 0L); +} + +/* + * Sets the topmost item in the viewport. + * Parameters: + * handle: Handle to the listbox to be cleared. + * top: Index to the top item. + */ +void API dw_listbox_set_top(HWND handle, int top) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + /* This doesn't work on comboboxes */ + if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0) + return; + + SendMessage(handle, LB_SETTOPINDEX, (WPARAM)top, 0); +} + +/* + * Adds text to an MLE box and returns the current point. + * Parameters: + * handle: Handle to the MLE to be queried. + * buffer: Text buffer to be imported. + * startpoint: Point to start entering text. + */ +unsigned int API dw_mle_import(HWND handle, char *buffer, int startpoint) +{ + int textlen, len = GetWindowTextLength(handle); + char *tmpbuf; + + if(startpoint < 0) + startpoint = 0; + + if(!buffer || (textlen = strlen(buffer)) < 1) + return startpoint; + + tmpbuf = calloc(1, len + textlen + startpoint + 2); + + if(len) + { + char *dest, *start; + int copylen = len - startpoint; + + GetWindowText(handle, tmpbuf, len+1); + + dest = &tmpbuf[startpoint+textlen]; + start = &tmpbuf[startpoint]; + + if(copylen > 0) + memcpy(dest, start, copylen); + } + memcpy(&tmpbuf[startpoint], buffer, textlen); + + SetWindowText(handle, tmpbuf); + + free(tmpbuf); + return (startpoint + textlen); +} + +/* + * Grabs text from an MLE box. + * Parameters: + * handle: Handle to the MLE to be queried. + * buffer: Text buffer to be exported. MUST allow for trailing nul character. + * startpoint: Point to start grabbing text. + * length: Amount of text to be grabbed. + */ +void API dw_mle_export(HWND handle, char *buffer, int startpoint, int length) +{ + int max, len = GetWindowTextLength(handle); + char *tmpbuf = calloc(1, len+2); + + if(len) + GetWindowText(handle, tmpbuf, len+1); + + buffer[0] = 0; + + if(startpoint < len) + { + max = MIN(length, len - startpoint); + + memcpy(buffer, &tmpbuf[startpoint], max); + buffer[max] = '\0'; + } + + free(tmpbuf); +} + +/* + * Obtains information about an MLE box. + * Parameters: + * handle: Handle to the MLE to be queried. + * bytes: A pointer to a variable to return the total bytes. + * lines: A pointer to a variable to return the number of lines. + */ +void API dw_mle_get_size(HWND handle, unsigned long *bytes, unsigned long *lines) +{ + if(bytes) + *bytes = GetWindowTextLength(handle); + if(lines) + *lines = (unsigned long)SendMessage(handle, EM_GETLINECOUNT, 0, 0); +} + +/* + * Deletes text from an MLE box. + * Parameters: + * handle: Handle to the MLE to be deleted from. + * startpoint: Point to start deleting text. + * length: Amount of text to be deleted. + */ +void API dw_mle_delete(HWND handle, int startpoint, int length) +{ + int len = GetWindowTextLength(handle); + char *tmpbuf = calloc(1, len+2); + + GetWindowText(handle, tmpbuf, len+1); + + if(startpoint + length < len) + { + strcpy(&tmpbuf[startpoint], &tmpbuf[startpoint+length]); + + SetWindowText(handle, tmpbuf); + } + + free(tmpbuf); +} + +/* + * Clears all text from an MLE box. + * Parameters: + * handle: Handle to the MLE to be cleared. + */ +void API dw_mle_clear(HWND handle) +{ + SetWindowText(handle, ""); +} + +/* + * Sets the visible line of an MLE box. + * Parameters: + * handle: Handle to the MLE. + * line: Line to be visible. + */ +void API dw_mle_set_visible(HWND handle, int line) +{ + int point = (int)SendMessage(handle, EM_LINEINDEX, (WPARAM)line, 0); + dw_mle_set_cursor(handle, point); +} + +/* + * Sets the editablity of an MLE box. + * Parameters: + * handle: Handle to the MLE. + * state: TRUE if it can be edited, FALSE for readonly. + */ +void API dw_mle_set_editable(HWND handle, int state) +{ + SendMessage(handle, EM_SETREADONLY, (WPARAM)(state ? FALSE : TRUE), 0); +} + +/* + * Sets the word wrap state of an MLE box. + * Parameters: + * handle: Handle to the MLE. + * state: TRUE if it wraps, FALSE if it doesn't. + */ +void API dw_mle_set_word_wrap(HWND handle, int state) +{ + /* If ES_AUTOHSCROLL is not set and there is not + * horizontal scrollbar it word wraps. + */ + if(state) + dw_window_set_style(handle, 0, ES_AUTOHSCROLL); + else + dw_window_set_style(handle, ES_AUTOHSCROLL, ES_AUTOHSCROLL); +} + +/* + * Sets the current cursor position of an MLE box. + * Parameters: + * handle: Handle to the MLE to be positioned. + * point: Point to position cursor. + */ +void API dw_mle_set_cursor(HWND handle, int point) +{ + SendMessage(handle, EM_SETSEL, 0, MAKELONG(point,point)); + SendMessage(handle, EM_SCROLLCARET, 0, 0); +} + +/* + * Finds text in an MLE box. + * Parameters: + * handle: Handle to the MLE to be cleared. + * text: Text to search for. + * point: Start point of search. + * flags: Search specific flags. + */ +int API dw_mle_search(HWND handle, char *text, int point, unsigned long flags) +{ + int len = GetWindowTextLength(handle); + char *tmpbuf = calloc(1, len+2); + int z, textlen, retval = 0; + + GetWindowText(handle, tmpbuf, len+1); + + textlen = strlen(text); + + if(flags & DW_MLE_CASESENSITIVE) + { + for(z=point;z<(len-textlen) && !retval;z++) + { + if(strncmp(&tmpbuf[z], text, textlen) == 0) + retval = z + textlen; + } + } + else + { + for(z=point;z<(len-textlen) && !retval;z++) + { + if(strnicmp(&tmpbuf[z], text, textlen) == 0) + retval = z + textlen; + } + } + + if(retval) + { + SendMessage(handle, EM_SETSEL, (WPARAM)retval - textlen, (LPARAM)retval); + SendMessage(handle, EM_SCROLLCARET, 0, 0); + } + + free(tmpbuf); + + return retval; +} + +/* + * Stops redrawing of an MLE box. + * Parameters: + * handle: Handle to the MLE to freeze. + */ +void API dw_mle_freeze(HWND handle) +{ +} + +/* + * Resumes redrawing of an MLE box. + * Parameters: + * handle: Handle to the MLE to thaw. + */ +void API dw_mle_thaw(HWND handle) +{ +} + +/* + * Sets the percent bar position. + * Parameters: + * handle: Handle to the percent bar to be set. + * position: Position of the percent bar withing the range. + */ +void API dw_percent_set_pos(HWND handle, unsigned int position) +{ + if(position == DW_PERCENT_INDETERMINATE) + { + /* If our common controls supports it... */ + if((dwComctlVer >= PACKVERSION(6,0))) + { + /* Enable the style on the control */ + SetWindowLong(handle, GWL_STYLE, GetWindowLong(handle, GWL_STYLE) | PBS_MARQUEE); + /* Start the bar going */ + SendMessage(handle, PBM_SETMARQUEE, 1, 100); + } + else + SendMessage(handle, PBM_SETPOS, 0, 0); + } + else + { + if((dwComctlVer >= PACKVERSION(6,0))) + { + unsigned long style = GetWindowLong(handle, GWL_STYLE); + + if(style & PBS_MARQUEE) + { + /* Stop the bar */ + SendMessage(handle, PBM_SETMARQUEE, 0, 0); + /* Disable the style on the control */ + SetWindowLong(handle, GWL_STYLE, style & ~PBS_MARQUEE); + } + } + /* Otherwise just set the position */ + SendMessage(handle, PBM_SETPOS, (WPARAM)position, 0); + } +} + +/* + * Returns the position of the slider. + * Parameters: + * handle: Handle to the slider to be queried. + */ +unsigned int API dw_slider_get_pos(HWND handle) +{ + int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0); + ULONG currentstyle = GetWindowLong(handle, GWL_STYLE); + + if(currentstyle & TBS_VERT) + return max - (unsigned int)SendMessage(handle, TBM_GETPOS, 0, 0); + return (unsigned int)SendMessage(handle, TBM_GETPOS, 0, 0); +} + +/* + * Sets the slider position. + * Parameters: + * handle: Handle to the slider to be set. + * position: Position of the slider withing the range. + */ +void API dw_slider_set_pos(HWND handle, unsigned int position) +{ + int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0); + ULONG currentstyle = GetWindowLong(handle, GWL_STYLE); + + if(currentstyle & TBS_VERT) + SendMessage(handle, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)max - position); + else + SendMessage(handle, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)position); +} + +/* + * Returns the position of the scrollbar. + * Parameters: + * handle: Handle to the scrollbar to be queried. + */ +unsigned int API dw_scrollbar_get_pos(HWND handle) +{ + return (unsigned int)SendMessage(handle, SBM_GETPOS, 0, 0); +} + +/* + * Sets the scrollbar position. + * Parameters: + * handle: Handle to the scrollbar to be set. + * position: Position of the scrollbar withing the range. + */ +void API dw_scrollbar_set_pos(HWND handle, unsigned int position) +{ + dw_window_set_data(handle, "_dw_scrollbar_value", (void *)position); + SendMessage(handle, SBM_SETPOS, (WPARAM)position, (LPARAM)TRUE); +} + +/* + * Sets the scrollbar range. + * Parameters: + * handle: Handle to the scrollbar to be set. + * range: Maximum range value. + * visible: Visible area relative to the range. + */ +void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible) +{ + SCROLLINFO si; + + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_RANGE | SIF_PAGE; + si.nMin = 0; + si.nMax = range - 1; + si.nPage = visible; + SendMessage(handle, SBM_SETSCROLLINFO, (WPARAM)TRUE, (LPARAM)&si); +} + +/* + * Sets the spinbutton value. + * Parameters: + * handle: Handle to the spinbutton to be set. + * position: Current value of the spinbutton. + */ +void API dw_spinbutton_set_pos(HWND handle, long position) +{ + char tmpbuf[101] = {0}; + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + + _snprintf(tmpbuf, 100, "%ld", position); + + if(cinfo && cinfo->buddy) + SetWindowText(cinfo->buddy, tmpbuf); + + SendMessage(handle, UDM_SETPOS32, 0, (LPARAM)position); +} + +/* + * Sets the spinbutton limits. + * Parameters: + * handle: Handle to the spinbutton to be set. + * position: Current value of the spinbutton. + * position: Current value of the spinbutton. + */ +void API dw_spinbutton_set_limits(HWND handle, long upper, long lower) +{ + SendMessage(handle, UDM_SETRANGE32, (WPARAM)lower,(LPARAM)upper); +} + +/* + * Sets the entryfield character limit. + * Parameters: + * handle: Handle to the spinbutton to be set. + * limit: Number of characters the entryfield will take. + */ +void API dw_entryfield_set_limit(HWND handle, ULONG limit) +{ + SendMessage(handle, EM_SETLIMITTEXT, (WPARAM)limit, 0); +} + +/* + * Returns the current value of the spinbutton. + * Parameters: + * handle: Handle to the spinbutton to be queried. + */ +long API dw_spinbutton_get_pos(HWND handle) +{ + return (long)SendMessage(handle, UDM_GETPOS32, 0, 0); +} + +/* + * Returns the state of the checkbox. + * Parameters: + * handle: Handle to the checkbox to be queried. + */ +int API dw_checkbox_get(HWND handle) +{ + if(SendMessage(handle, BM_GETCHECK, 0, 0) == BST_CHECKED) + return (in_checkbox_handler ? FALSE : TRUE); + return (in_checkbox_handler ? TRUE : FALSE); +} + +/* This function unchecks all radiobuttons on a box */ +BOOL CALLBACK _uncheck_radios(HWND handle, LPARAM lParam) +{ + char tmpbuf[100]; + + GetClassName(handle, tmpbuf, 99); + + if(strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0) + { + BubbleButton *bubble= (BubbleButton *)GetWindowLongPtr(handle, GWLP_USERDATA); + + if(bubble && !bubble->checkbox) + SendMessage(handle, BM_SETCHECK, 0, 0); + } + return TRUE; +} +/* + * Sets the state of the checkbox. + * Parameters: + * handle: Handle to the checkbox to be queried. + * value: TRUE for checked, FALSE for unchecked. + */ +void API dw_checkbox_set(HWND handle, int value) +{ + BubbleButton *bubble= (BubbleButton *)GetWindowLongPtr(handle, GWLP_USERDATA); + + if(bubble && !bubble->checkbox) + { + HWND parent = GetParent(handle); + + if(parent) + EnumChildWindows(parent, _uncheck_radios, 0); + } + SendMessage(handle, BM_SETCHECK, (WPARAM)value, 0); +} + +/* + * Inserts an item into a tree window (widget) after another item. + * Parameters: + * handle: Handle to the tree to be inserted. + * item: Handle to the item to be positioned after. + * title: The text title of the entry. + * icon: Handle to coresponding icon. + * parent: Parent handle or 0 if root. + * itemdata: Item specific data. + */ +HTREEITEM API dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, HICN icon, HTREEITEM parent, void *itemdata) +{ + 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 = title; + tvi.lParam = (LONG)ptrs; + tvi.cchTextMax = strlen(title); + tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1); + + tvins.item = tvi; + tvins.hParent = parent; + tvins.hInsertAfter = item ? item : TVI_FIRST; + + hti = TreeView_InsertItem(handle, &tvins); + + return hti; +} + +/* + * Inserts an item into a tree window (widget). + * Parameters: + * handle: Handle to the tree to be inserted. + * title: The text title of the entry. + * icon: Handle to coresponding icon. + * parent: Parent handle or 0 if root. + * itemdata: Item specific data. + */ +HTREEITEM API dw_tree_insert(HWND handle, char *title, HICN icon, HTREEITEM parent, void *itemdata) +{ + 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 = title; + tvi.lParam = (LONG)ptrs; + tvi.cchTextMax = strlen(title); + tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1); + + tvins.item = tvi; + tvins.hParent = parent; + tvins.hInsertAfter = TVI_LAST; + + hti = TreeView_InsertItem(handle, &tvins); + + return hti; +} + +/* + * Sets the text and icon of an item in a tree window (widget). + * Parameters: + * handle: Handle to the tree containing the item. + * item: Handle of the item to be modified. + * title: The text title of the entry. + * icon: Handle to coresponding icon. + */ +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 = title; + tvi.cchTextMax = strlen(title); + tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1); + tvi.hItem = (HTREEITEM)item; + + TreeView_SetItem(handle, &tvi); + } +} + +/* + * Sets the item data of a tree item. + * Parameters: + * handle: Handle to the tree containing the item. + * item: Handle of the item to be modified. + * itemdata: User defined data to be associated with item. + */ +void API dw_tree_item_set_data(HWND handle, HTREEITEM item, void *itemdata) +{ + TVITEM tvi; + void **ptrs; + + tvi.mask = TVIF_HANDLE; + tvi.hItem = item; + + if(TreeView_GetItem(handle, &tvi)) + { + ptrs = (void **)tvi.lParam; + ptrs[1] = itemdata; + } +} + +/* + * Gets the item data of a tree item. + * Parameters: + * handle: Handle to the tree containing the item. + * item: Handle of the item to be modified. + */ +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 NULL; +} + +/* + * Gets the text an item in a tree window (widget). + * Parameters: + * handle: Handle to the tree containing the item. + * item: Handle of the item to be modified. + */ +char * API dw_tree_get_title(HWND handle, HTREEITEM item) +{ + TVITEM tvi; + + tvi.mask = TVIF_HANDLE; + tvi.hItem = item; + + if(TreeView_GetItem(handle, &tvi)) + return tvi.pszText; + return NULL; +} + +/* + * Gets the text an item in a tree window (widget). + * Parameters: + * handle: Handle to the tree containing the item. + * item: Handle of the item to be modified. + */ +HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item) +{ + return TreeView_GetParent(handle, item); +} + +/* + * Sets this item as the active selection. + * Parameters: + * handle: Handle to the tree window (widget) to be selected. + * item: Handle to the item to be selected. + */ +void API dw_tree_item_select(HWND handle, HTREEITEM item) +{ + dw_window_set_data(handle, "_dw_select_item", (void *)1); + TreeView_SelectItem(handle, item); + dw_window_set_data(handle, "_dw_select_item", (void *)0); +} + +/* 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: + * handle: Handle to the window (widget) to be cleared. + */ +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); +} + +/* + * Expands a node on a tree. + * Parameters: + * handle: Handle to the tree window (widget). + * item: Handle to node to be expanded. + */ +void API dw_tree_item_expand(HWND handle, HTREEITEM item) +{ + TreeView_Expand(handle, item, TVE_EXPAND); +} + +/* + * Collapses a node on a tree. + * Parameters: + * handle: Handle to the tree window (widget). + * item: Handle to node to be collapsed. + */ +void API dw_tree_item_collapse(HWND handle, HTREEITEM item) +{ + TreeView_Expand(handle, item, TVE_COLLAPSE); +} + +/* + * Removes a node from a tree. + * Parameters: + * handle: Handle to the window (widget) to be cleared. + * item: Handle to node to be deleted. + */ +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); +} + +/* + * Sets up the container columns. + * Parameters: + * handle: Handle to the container to be configured. + * flags: An array of unsigned longs with column flags. + * titles: An array of strings with column text titles. + * count: The number of columns (this should match the arrays). + * separator: The column number that contains the main separator. + * (only used on OS/2 but must be >= 0 on all) + */ +int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator) +{ + ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + int z, l = 0; + unsigned long *tempflags = calloc(sizeof(unsigned long), count + 2); + LVCOLUMN lvc; + + if(separator == -1) + { + tempflags[0] = DW_CFA_RESERVED; + l = 1; + } + + memcpy(&tempflags[l], flags, sizeof(unsigned long) * count); + tempflags[count + l] = 0; + cinfo->flags = tempflags; + cinfo->columns = count + l; + + + for(z=0;z<count;z++) + { + if(titles[z]) + { + lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_FMT; + lvc.pszText = titles[z]; + lvc.cchTextMax = strlen(titles[z]); + if(flags[z] & DW_CFA_RIGHT) + lvc.fmt = LVCFMT_RIGHT; + else if(flags[z] & DW_CFA_CENTER) + lvc.fmt = LVCFMT_CENTER; + else + lvc.fmt = LVCFMT_LEFT; + lvc.cx = 75; + lvc.iSubItem = count; + SendMessage(handle, LVM_INSERTCOLUMN, (WPARAM)z + l, (LPARAM)&lvc); + } + } + ListView_SetExtendedListViewStyle(handle, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES); + return DW_ERROR_NONE; +} + +/* + * Sets up the filesystem columns, note: filesystem always has an icon/filename field. + * Parameters: + * handle: Handle to the container to be configured. + * flags: An array of unsigned longs with column flags. + * titles: An array of strings with column text titles. + * count: The number of columns (this should match the arrays). + */ +int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count) +{ + LV_COLUMN lvc; + + lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + lvc.pszText = "Filename"; + lvc.cchTextMax = 8; + lvc.fmt = 0; + if(!count) + lvc.cx = 300; + else + lvc.cx = 150; + lvc.iSubItem = count; + SendMessage(handle, LVM_INSERTCOLUMN, (WPARAM)0, (LPARAM)&lvc); + dw_container_setup(handle, flags, titles, count, -1); + return DW_ERROR_NONE; +} + +/* + * Obtains an icon from a module (or header in GTK). + * Parameters: + * module: Handle to module (DLL) in OS/2 and Windows. + * id: A unsigned long id int the resources on OS/2 and + * Windows, on GTK this is converted to a pointer + * to an embedded XPM. + */ +HICN API dw_icon_load(unsigned long module, unsigned long id) +{ + return (HICN)LoadIcon(DWInstance, MAKEINTRESOURCE(id)); +} + +/* + * Obtains an icon from a file. + * Parameters: + * filename: Name of the file, omit extention to have + * DW pick the appropriate file extension. + * (ICO on OS/2 or Windows, XPM on Unix) + */ +HICN API dw_icon_load_from_file(char *filename) +{ +#ifdef GDIPLUS + return _dw_load_icon(filename); +#else + char *file = malloc(strlen(filename) + 5); + HANDLE icon; + + if(!file) + return 0; + + strcpy(file, filename); + + /* check if we can read from this file (it exists and read permission) */ + if(access(file, 04) != 0) + { + /* Try with .bmp extention */ + strcat(file, ".ico"); + if(access(file, 04) != 0) + { + free(file); + return 0; + } + } + icon = LoadImage(NULL, file, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + free(file); + return (HICN)icon; +#endif +} + +/* + * Obtains an icon from data + * Parameters: + * data: Source of icon data + * DW pick the appropriate file extension. + * (ICO on OS/2 or Windows, XPM on Unix) + */ +HICN API dw_icon_load_from_data(char *data, int len) +{ + HANDLE icon; + char *file; + FILE *fp; + + if ( !data ) + return 0; + file = _tempnam( _dw_alternate_temp_dir, "dw" ); + if ( file != NULL ) + { + fp = fopen( file, "wb" ); + if ( fp != NULL ) + { + fwrite( data, 1, len, fp ); + fclose( fp ); +#ifdef GDIPLUS + icon = _dw_load_icon(file); +#else + icon = LoadImage( NULL, file, IMAGE_ICON, 0, 0, LR_LOADFROMFILE ); +#endif + } + else + { + unlink( file ); + free( file ); + return 0; + } + unlink( file ); + free( file ); + } + return (HICN)icon; +} + +/* + * Frees a loaded resource in OS/2 and Windows. + * Parameters: + * handle: Handle to icon returned by dw_icon_load(). + */ +void API dw_icon_free(HICN handle) +{ + DestroyIcon((HICON)handle); +} + +/* + * Allocates memory used to populate a container. + * Parameters: + * handle: Handle to the container window (widget). + * rowcount: The number of items to be populated. + */ +void * API dw_container_alloc(HWND handle, int rowcount) +{ + LV_ITEM lvi; + int z, item; + + lvi.mask = LVIF_DI_SETITEM | LVIF_TEXT | LVIF_IMAGE; + lvi.iSubItem = 0; + /* Insert at the end */ + lvi.iItem = 1000000; + lvi.pszText = ""; + lvi.cchTextMax = 1; + lvi.iImage = -1; + + ShowWindow(handle, SW_HIDE); + item = ListView_InsertItem(handle, &lvi); + for(z=1;z<rowcount;z++) + ListView_InsertItem(handle, &lvi); + dw_window_set_data(handle, "_dw_insertitem", (void *)item); + return (void *)handle; +} + +/* Finds a icon in the table, otherwise it adds it to the table + * and returns the index in the table. + */ +int _lookup_icon(HWND handle, HICON hicon, int type) +{ + int z; + static HWND lasthwnd = NULL; + + if(!hSmall || !hLarge) + { + hSmall = ImageList_Create(16, 16, ILC_COLOR16 | ILC_MASK, ICON_INDEX_LIMIT, 0); + hLarge = ImageList_Create(32, 32, ILC_COLOR16 | ILC_MASK, ICON_INDEX_LIMIT, 0); + } + for(z=0;z<ICON_INDEX_LIMIT;z++) + { + if(!lookup[z]) + { + lookup[z] = hicon; + ImageList_AddIcon(hSmall, hicon); + ImageList_AddIcon(hLarge, hicon); + if(type) + { + TreeView_SetImageList(handle, hSmall, TVSIL_NORMAL); + } + else + { + ListView_SetImageList(handle, hSmall, LVSIL_SMALL); + ListView_SetImageList(handle, hLarge, LVSIL_NORMAL); + } + lasthwnd = handle; + return z; + } + + if(hicon == lookup[z]) + { + if(lasthwnd != handle) + { + if(type) + { + TreeView_SetImageList(handle, hSmall, TVSIL_NORMAL); + } + else + { + ListView_SetImageList(handle, hSmall, LVSIL_SMALL); + ListView_SetImageList(handle, hLarge, LVSIL_NORMAL); + } + lasthwnd = handle; + } + return z; + } + } + return -1; +} + +/* + * Sets an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, HICN icon) +{ + LV_ITEM lvi; + int item = 0; + + if(pointer) + { + item = (int)dw_window_get_data(handle, "_dw_insertitem"); + } + + lvi.iItem = row + item; + lvi.iSubItem = 0; + lvi.mask = LVIF_DI_SETITEM | LVIF_IMAGE | LVIF_TEXT; + lvi.pszText = filename; + lvi.cchTextMax = strlen(filename); + lvi.iImage = _lookup_icon(handle, (HICON)icon, 0); + + ListView_SetItem(handle, &lvi); +} + +/* + * Sets an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data) +{ + dw_container_set_item(handle, pointer, column + 1, row, data); +} + +/* + * Sets an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data) +{ + ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + ULONG *flags; + LV_ITEM lvi; + char textbuffer[101] = {0}, *destptr = textbuffer; + int item = 0; + + if(pointer) + { + item = (int)dw_window_get_data(handle, "_dw_insertitem"); + } + + if(!cinfo || !cinfo->flags || !data) + return; + + flags = cinfo->flags; + + lvi.mask = LVIF_DI_SETITEM | LVIF_TEXT; + lvi.iItem = row + item; + lvi.iSubItem = column; + + if(flags[column] & DW_CFA_BITMAPORICON) + { + HICON hicon = *((HICON *)data); + + lvi.mask = LVIF_DI_SETITEM | LVIF_IMAGE; + lvi.pszText = NULL; + lvi.cchTextMax = 0; + + lvi.iImage = _lookup_icon(handle, hicon, 0); + } + else if(flags[column] & DW_CFA_STRING) + { + char *tmp = *((char **)data); + + if(!tmp) + tmp = ""; + + lvi.pszText = tmp; + lvi.cchTextMax = strlen(tmp); + destptr = tmp; + } + else if(flags[column] & DW_CFA_ULONG) + { + ULONG tmp = *((ULONG *)data); + + _snprintf(textbuffer, 100, "%lu", tmp); + + lvi.pszText = textbuffer; + lvi.cchTextMax = strlen(textbuffer); + } + else if(flags[column] & DW_CFA_DATE) + { + struct tm curtm; + CDATE cdate = *((CDATE *)data); + + memset(&curtm, 0, sizeof(struct tm)); + + /* Safety check... zero dates are crashing + * Visual Studio 2008. -Brian + */ + if(cdate.year > 1900 && cdate.year < 2100) + { + curtm.tm_mday = (cdate.day >= 0 && cdate.day < 32) ? cdate.day : 1; + curtm.tm_mon = (cdate.month > 0 && cdate.month < 13) ? cdate.month - 1 : 0; + curtm.tm_year = cdate.year - 1900; + strftime(textbuffer, 100, "%x", &curtm); + } + else + { + textbuffer[0] = 0; + } + + lvi.pszText = textbuffer; + lvi.cchTextMax = strlen(textbuffer); + } + else if(flags[column] & DW_CFA_TIME) + { + struct tm curtm; + CTIME ctime = *((CTIME *)data); + + curtm.tm_hour = (ctime.hours >= 0 && ctime.hours < 24) ? ctime.hours : 0; + curtm.tm_min = (ctime.minutes >= 0 && ctime.minutes < 60) ? ctime.minutes : 0; + curtm.tm_sec = (ctime.seconds >= 0 && ctime.seconds < 60) ? ctime.seconds : 0; + + strftime(textbuffer, 100, "%X", &curtm); + + lvi.pszText = textbuffer; + lvi.cchTextMax = strlen(textbuffer); + } + + ListView_SetItem(handle, &lvi); +} + +/* + * Changes an existing item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_container_change_item(HWND handle, int column, int row, void *data) +{ + dw_container_set_item(handle, NULL, column, row, data); +} + +/* + * Changes an existing item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_filesystem_change_item(HWND handle, int column, int row, void *data) +{ + dw_filesystem_set_item(handle, NULL, column, row, data); +} + +/* + * Changes an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void API dw_filesystem_change_file(HWND handle, int row, char *filename, HICN icon) +{ + dw_filesystem_set_file(handle, NULL, row, filename, icon); +} + +/* + * Gets column type for a container column + * Parameters: + * handle: Handle to the container window (widget). + * column: Zero based column. + */ +int API dw_container_get_column_type(HWND handle, int column) +{ + ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + ULONG *flags; + int rc; + + if(!cinfo || !cinfo->flags) + return 0; + + flags = cinfo->flags; + + if(flags[column] & DW_CFA_BITMAPORICON) + rc = DW_CFA_BITMAPORICON; + else if(flags[column] & DW_CFA_STRING) + rc = DW_CFA_STRING; + else if(flags[column] & DW_CFA_ULONG) + rc = DW_CFA_ULONG; + else if(flags[column] & DW_CFA_DATE) + rc = DW_CFA_DATE; + else if(flags[column] & DW_CFA_TIME) + rc = DW_CFA_TIME; + else + rc = 0; + return rc; +} + +/* + * Gets column type for a filesystem container column + * Parameters: + * handle: Handle to the container window (widget). + * column: Zero based column. + */ +int API dw_filesystem_get_column_type(HWND handle, int column) +{ + return dw_container_get_column_type( handle, column + 1 ); +} + +/* + * Sets the alternating row colors for container window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * oddcolor: Odd row background color in DW_RGB format or a default color index. + * evencolor: Even row background color in DW_RGB format or a default color index. + * DW_RGB_TRANSPARENT will disable coloring rows. + * DW_CLR_DEFAULT will use the system default alternating row colors. + */ +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; +} + +/* + * Sets the width of a column in the container. + * Parameters: + * handle: Handle to window (widget) of container. + * column: Zero based column of width being set. + * width: Width of column in pixels. + */ +void API dw_container_set_column_width(HWND handle, int column, int width) +{ + ListView_SetColumnWidth(handle, column, width); +} + +/* Internal version that handles both types */ +void _dw_container_set_row_title(HWND handle, void *pointer, int row, char *title) +{ + LV_ITEM lvi; + int item = 0; + + if(pointer) + { + item = (int)dw_window_get_data(handle, "_dw_insertitem"); + } + + 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; + +} + +/* + * Sets the title 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. + * title: String title of the item. + */ +void API dw_container_set_row_title(void *pointer, int row, char *title) +{ + _dw_container_set_row_title(pointer, pointer, row, title); +} + +/* + * Changes the title of a row already inserted in the container. + * Parameters: + * handle: Handle to the container window (widget). + * row: Zero based row of data being set. + * title: String title of the item. + */ +void API dw_container_change_row_title(HWND handle, int row, char *title) +{ + _dw_container_set_row_title(handle, NULL, row, title); +} + +/* + * Sets the title of a row in the container. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * rowcount: The number of rows to be inserted. + */ +void API dw_container_insert(HWND handle, void *pointer, int rowcount) +{ + ShowWindow(handle, SW_SHOW); +} + +/* + * Removes all rows from a container. + * Parameters: + * handle: Handle to the window (widget) to be cleared. + * redraw: TRUE to cause the container to redraw immediately. + */ +void API dw_container_clear(HWND handle, int redraw) +{ + ListView_DeleteAllItems(handle); +} + +/* + * Removes the first x rows from a container. + * Parameters: + * handle: Handle to the window (widget) to be deleted from. + * rowcount: The number of rows to be deleted. + */ +void API dw_container_delete(HWND handle, int rowcount) +{ + int z, _index = (int)dw_window_get_data(handle, "_dw_index"); + + for(z=0;z<rowcount;z++) + { + ListView_DeleteItem(handle, 0); + } + if(rowcount > _index) + dw_window_set_data(handle, "_dw_index", 0); + else + dw_window_set_data(handle, "_dw_index", (void *)(_index - rowcount)); +} + +/* + * Scrolls container up or down. + * Parameters: + * handle: Handle to the window (widget) to be scrolled. + * direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or + * DW_SCROLL_BOTTOM. (rows is ignored for last two) + * rows: The number of rows to be scrolled. + */ +void API dw_container_scroll(HWND handle, int direction, long rows) +{ + switch(direction) + { + case DW_SCROLL_TOP: + ListView_Scroll(handle, 0, -10000000); + break; + case DW_SCROLL_BOTTOM: + ListView_Scroll(handle, 0, 10000000); + break; + } +} + +/* + * Starts a new query of a container. + * Parameters: + * handle: Handle to the window (widget) to be queried. + * flags: If this parameter is DW_CRA_SELECTED it will only + * return items that are currently selected. Otherwise + * it will return all records in the container. + */ +char * API dw_container_query_start(HWND handle, unsigned long flags) +{ + LV_ITEM lvi; + int _index = ListView_GetNextItem(handle, -1, flags); + + if(_index == -1) + return NULL; + + 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; +} + +/* + * Continues an existing query of a container. + * Parameters: + * handle: Handle to the window (widget) to be queried. + * flags: If this parameter is DW_CRA_SELECTED it will only + * return items that are currently selected. Otherwise + * it will return all records in the container. + */ +char * API dw_container_query_next(HWND handle, unsigned long flags) +{ + LV_ITEM lvi; + int _index = (int)dw_window_get_data(handle, "_dw_index"); + + _index = ListView_GetNextItem(handle, _index, flags); + + if(_index == -1) + return NULL; + + 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; +} + +/* + * 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(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; + + memset(&lvi, 0, sizeof(LV_ITEM)); + + lvi.iItem = index; + lvi.mask = LVIF_PARAM; + + ListView_GetItem( handle, &lvi ); + + if ( (textcomp && lvi.lParam && strcmp( (char *)lvi.lParam, text ) == 0) || (!textcomp && (char *)lvi.lParam == text) ) + { + + ListView_SetItemState( handle, index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED ); + ListView_EnsureVisible( handle, index, TRUE ); + return; + } + + 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(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; + + memset(&lvi, 0, sizeof(LV_ITEM)); + + lvi.iItem = index; + 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"); + + if(index < _index) + dw_window_set_data(handle, "_dw_index", (void *)(_index - 1)); + + ListView_DeleteItem(handle, index); + return; + } + + index = ListView_GetNextItem(handle, index, LVNI_ALL); + } +} + +/* + * Optimizes the column widths so that all data is visible. + * Parameters: + * handle: Handle to the window (widget) to be optimized. + */ +void API dw_container_optimize(HWND handle) +{ + ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + if(cinfo && cinfo->columns == 1) + { + ListView_SetColumnWidth(handle, 0, LVSCW_AUTOSIZE); + } + else if(cinfo && cinfo->columns > 1) + { + int z, index; + ULONG *flags = cinfo->flags, *columns = calloc(sizeof(ULONG), cinfo->columns); + char *text = malloc(1024); + + /* Initialize with sizes of column labels */ + for(z=0;z<cinfo->columns;z++) + { + if(flags[z] & DW_CFA_BITMAPORICON) + columns[z] = 5; + else + { + LVCOLUMN lvc; + + lvc.mask = LVCF_TEXT; + lvc.cchTextMax = 1023; + lvc.pszText = text; + + if(ListView_GetColumn(handle, z, &lvc)) + columns[z] = ListView_GetStringWidth(handle, lvc.pszText); + + if(flags[z] & DW_CFA_RESERVED) + columns[z] += 20; + } + } + + index = ListView_GetNextItem(handle, -1, LVNI_ALL); + + /* Query all the item texts */ + while(index != -1) + { + for(z=0;z<cinfo->columns;z++) + { + LV_ITEM lvi; + + memset(&lvi, 0, sizeof(LV_ITEM)); + + lvi.iItem = index; + lvi.iSubItem = z; + lvi.mask = LVIF_TEXT; + lvi.cchTextMax = 1023; + lvi.pszText = text; + + if(ListView_GetItem(handle, &lvi)) + { + int width = ListView_GetStringWidth(handle, lvi.pszText); + if(width > columns[z]) + { + if(z == 0) + columns[z] = width + 20; + else + columns[z] = width; + } + } + } + + index = ListView_GetNextItem(handle, index, LVNI_ALL); + } + + /* Set the new sizes */ + for(z=0;z<cinfo->columns;z++) + ListView_SetColumnWidth(handle, z, columns[z] + 16); + + free(columns); + free(text); + } +} + +/* + * Inserts an icon into the taskbar. + * Parameters: + * handle: Window handle that will handle taskbar icon messages. + * icon: Icon handle to display in the taskbar. + * bubbletext: Text to show when the mouse is above the icon. + */ +void API dw_taskbar_insert(HWND handle, HICN icon, char *bubbletext) +{ + NOTIFYICONDATA tnid; + + tnid.cbSize = sizeof(NOTIFYICONDATA); + tnid.hWnd = handle; + tnid.uID = (UINT)icon; + tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; + tnid.uCallbackMessage = WM_USER+2; + tnid.hIcon = (HICON)icon; + if(bubbletext) + strncpy(tnid.szTip, bubbletext, sizeof(tnid.szTip)); + else + tnid.szTip[0] = 0; + + Shell_NotifyIcon(NIM_ADD, &tnid); +} + +/* + * Deletes an icon from the taskbar. + * Parameters: + * handle: Window handle that was used with dw_taskbar_insert(). + * icon: Icon handle that was used with dw_taskbar_insert(). + */ +void API dw_taskbar_delete(HWND handle, HICN icon) +{ + NOTIFYICONDATA tnid; + + tnid.cbSize = sizeof(NOTIFYICONDATA); + tnid.hWnd = handle; + tnid.uID = (UINT)icon; + + Shell_NotifyIcon(NIM_DELETE, &tnid); +} + +/* + * Creates a rendering context widget (window) to be packed. + * Parameters: + * id: An id to be used with dw_window_from_id. + * Returns: + * A handle to the widget or NULL on failure. + */ +HWND API dw_render_new(unsigned long id) +{ + Box *newbox = calloc(sizeof(Box), 1); + HWND tmp = CreateWindow(ObjectClassName, + "", + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, + 0,0,screenx,screeny, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + newbox->pad = 0; + newbox->type = 0; + newbox->count = 0; + newbox->grouphwnd = (HWND)NULL; + newbox->cinfo.pOldProc = SubclassWindow(tmp, _rendwndproc); + newbox->cinfo.fore = newbox->cinfo.back = -1; + SetWindowLongPtr( tmp, GWLP_USERDATA, (LONG_PTR)newbox ); + return tmp; +} + +/* Sets the current foreground drawing color. + * Parameters: + * red: red value. + * green: green value. + * blue: blue value. + */ +void API dw_color_foreground_set(unsigned long value) +{ + HPEN hPen = TlsGetValue(_hPen); + HBRUSH hBrush = TlsGetValue(_hBrush); + COLORREF foreground; + + value = _internal_color(value); + foreground = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value)); + + DeleteObject(hPen); + DeleteObject(hBrush); + TlsSetValue(_foreground, (LPVOID)foreground); + TlsSetValue(_hPen, CreatePen(PS_SOLID, 1, foreground)); + TlsSetValue(_hBrush, CreateSolidBrush(foreground)); +} + +/* Sets the current background drawing color. + * Parameters: + * red: red value. + * green: green value. + * blue: blue value. + */ +void API dw_color_background_set(unsigned long value) +{ + COLORREF background; + + value = _internal_color(value); + background = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value)); + + if(value == DW_RGB_TRANSPARENT) + TlsSetValue(_background, (LPVOID)DW_RGB_TRANSPARENT); + else + TlsSetValue(_background, (LPVOID)background); +} + +/* Allows the user to choose a color using the system's color chooser dialog. + * Parameters: + * value: current color + * Returns: + * The selected color or the current color if cancelled. + */ +unsigned long API dw_color_choose(unsigned long value) +{ + CHOOSECOLOR cc; + unsigned long newcolor; + COLORREF acrCustClr[16] = {0}; + + value = _internal_color(value); + if(value == DW_RGB_TRANSPARENT) + newcolor = DW_RGB_TRANSPARENT; + else + newcolor = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value)); + ZeroMemory(&cc, sizeof(CHOOSECOLOR)); + cc.lStructSize = sizeof(CHOOSECOLOR); + cc.rgbResult = newcolor; + cc.hwndOwner = HWND_DESKTOP; + cc.lpCustColors = (LPDWORD)acrCustClr; + cc.Flags = CC_FULLOPEN | CC_RGBINIT; + if (ChooseColor(&cc) == TRUE) + newcolor = DW_RGB(DW_RED_VALUE(cc.rgbResult), DW_GREEN_VALUE(cc.rgbResult), DW_BLUE_VALUE(cc.rgbResult)); + return newcolor; +} + +/* Draw a point on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * x: X coordinate. + * y: Y coordinate. + */ +void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y) +{ + HDC hdcPaint; + + if(handle) + hdcPaint = GetDC(handle); + else if(pixmap) + hdcPaint = pixmap->hdc; + else + return; + + SetPixel(hdcPaint, x, y, (COLORREF)TlsGetValue(_foreground)); + if(!pixmap) + ReleaseDC(handle, hdcPaint); +} + +/* Draw a line on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * x1: First X coordinate. + * y1: First Y coordinate. + * x2: Second X coordinate. + * y2: Second Y coordinate. + */ +void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2) +{ + HDC hdcPaint; + HPEN oldPen; + + if(handle) + hdcPaint = GetDC(handle); + else if(pixmap) + hdcPaint = pixmap->hdc; + else + return; + + oldPen = SelectObject(hdcPaint, TlsGetValue(_hPen)); + MoveToEx(hdcPaint, x1, y1, NULL); + LineTo(hdcPaint, x2, y2); + SelectObject(hdcPaint, oldPen); + /* For some reason Win98 (at least) fails + * to draw the last pixel. So I do it myself. + */ + SetPixel(hdcPaint, x2, y2, (COLORREF)TlsGetValue(_foreground)); + if(!pixmap) + ReleaseDC(handle, hdcPaint); +} + +/* Draw a closed polygon on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * flags: DW_DRAW_FILL (1) to fill the polygon or DW_DRAW_DEFAULT (0). + * number of points + * x[]: X coordinates. + * y[]: Y coordinates. + */ +void API dw_draw_polygon(HWND handle, HPIXMAP pixmap, int flags, int npoints, int *x, int *y) +{ + HDC hdcPaint; + HBRUSH oldBrush; + HPEN oldPen; + POINT *points; + int i; + + if ( handle ) + hdcPaint = GetDC( handle ); + else if ( pixmap ) + hdcPaint = pixmap->hdc; + else + return; + if ( npoints ) + { + /* + * Allocate enough space for the number of points supplied plus 1. + * Under windows, unless the first and last points are the same + * the polygon won't be closed + */ + points = (POINT *)malloc( (npoints+1) * sizeof(POINT) ); + /* + * should check for NULL pointer return! + */ + for ( i = 0 ; i < npoints ; i++ ) + { + points[i].x = x[i]; + points[i].y = y[i]; + } + if ( !( points[0].x == points[npoints-1].x + && points[0].y == points[npoints-1].y ) ) + { + /* set the last point to be the same as the first point... */ + points[npoints].x = points[0].x; + points[npoints].y = points[0].y; + /* ... and increment the number of points */ + npoints++; + } + } + + oldBrush = SelectObject( hdcPaint, TlsGetValue(_hBrush) ); + oldPen = SelectObject( hdcPaint, TlsGetValue(_hPen) ); + if ( flags & DW_DRAW_FILL ) + Polygon( hdcPaint, points, npoints ); + else + Polyline( hdcPaint, points, npoints ); + SelectObject( hdcPaint, oldBrush ); + SelectObject( hdcPaint, oldPen ); + if ( !pixmap ) + ReleaseDC( handle, hdcPaint ); + free(points); +} + +/* Draw a rectangle on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * flags: DW_DRAW_FILL (1) to fill the box or DW_DRAW_DEFAULT (0). + * x: X coordinate. + * y: Y coordinate. + * width: Width of rectangle. + * height: Height of rectangle. + */ +void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int flags, int x, int y, int width, int height) +{ + HDC hdcPaint; + RECT Rect; + + if(handle) + hdcPaint = GetDC(handle); + else if(pixmap) + hdcPaint = pixmap->hdc; + else + return; + + SetRect(&Rect, x, y, x + width , y + height ); + if(flags & DW_DRAW_FILL) + FillRect(hdcPaint, &Rect, TlsGetValue(_hBrush)); + else + FrameRect(hdcPaint, &Rect, TlsGetValue(_hBrush)); + if(!pixmap) + ReleaseDC(handle, hdcPaint); +} + +/* Draw an arc on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * flags: DW_DRAW_FILL (1) to fill the arc or DW_DRAW_DEFAULT (0). + * DW_DRAW_FULL will draw a complete circle/elipse. + * xorigin: X coordinate of center of arc. + * yorigin: Y coordinate of center of arc. + * x1: X coordinate of first segment of arc. + * y1: Y coordinate of first segment of arc. + * x2: X coordinate of second segment of arc. + * y2: Y coordinate of second segment of arc. + */ +void API dw_draw_arc(HWND handle, HPIXMAP pixmap, int flags, int xorigin, int yorigin, int x1, int y1, int x2, int y2) +{ + HDC hdcPaint; + HBRUSH oldBrush; + HPEN oldPen; + double dx = xorigin - x1; + double dy = yorigin - y1; + double r = sqrt(dx*dx + dy*dy); + + if(handle) + hdcPaint = GetDC(handle); + else if(pixmap) + hdcPaint = pixmap->hdc; + else + return; + + if(flags & DW_DRAW_FILL) + oldBrush = SelectObject( hdcPaint, TlsGetValue(_hBrush) ); + else + oldBrush = SelectObject( hdcPaint, GetStockObject(HOLLOW_BRUSH) ); + oldPen = SelectObject( hdcPaint, TlsGetValue(_hPen) ); + if(flags & DW_DRAW_FULL) + Ellipse(hdcPaint, x1, y1, x2, y2); + else + Arc(hdcPaint, xorigin-r, yorigin-r, xorigin+r, yorigin+r, x2, y2, x1, y1); + SelectObject( hdcPaint, oldBrush ); + SelectObject( hdcPaint, oldPen ); + + if(!pixmap) + ReleaseDC(handle, hdcPaint); +} + +/* Draw text on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * x: X coordinate. + * y: Y coordinate. + * text: Text to be displayed. + */ +void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text) +{ + HDC hdc; + int mustdelete = 0; + HFONT hFont = 0, oldFont = 0; + ColorInfo *cinfo = NULL; + COLORREF background; + + if(handle) + hdc = GetDC(handle); + else if(pixmap) + hdc = pixmap->hdc; + else + return; + + if(handle) + cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + else if(pixmap->font) + hFont = pixmap->font; + else if(pixmap->handle) + cinfo = (ColorInfo *)GetWindowLongPtr(pixmap->handle, GWLP_USERDATA); + + if(cinfo) + { + hFont = _acquire_font(handle, cinfo->fontname); + mustdelete = 1; + } + + background = (COLORREF)TlsGetValue(_background); + if(hFont) + oldFont = SelectObject(hdc, hFont); + SetTextColor(hdc, (COLORREF)TlsGetValue(_foreground)); + if(background == DW_RGB_TRANSPARENT) + SetBkMode(hdc, TRANSPARENT); + else + { + SetBkMode(hdc, OPAQUE); + SetBkColor(hdc, background); + } + TextOut(hdc, x, y, text, strlen(text)); + if(oldFont) + SelectObject(hdc, oldFont); + if(mustdelete) + DeleteObject(hFont); + if(!pixmap) + ReleaseDC(handle, hdc); +} + +/* Query the width and height of a text string. + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * text: Text to be queried. + * width: Pointer to a variable to be filled in with the width. + * height Pointer to a variable to be filled in with the height. + */ +void API dw_font_text_extents_get(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height) +{ + HDC hdc; + int mustdelete = 0; + HFONT hFont = NULL, oldFont; + SIZE sz; + + if(handle) + hdc = GetDC(handle); + else if(pixmap) + hdc = pixmap->hdc; + else + return; + + if(pixmap && pixmap->font) + { + hFont = pixmap->font; + } + else + { + ColorInfo *cinfo; + + if(handle) + cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA); + else + cinfo = (ColorInfo *)GetWindowLongPtr(pixmap->handle, GWLP_USERDATA); + + if(cinfo) + { + hFont = _acquire_font(handle, cinfo->fontname); + mustdelete = 1; + } + } + oldFont = SelectObject(hdc, hFont); + + GetTextExtentPoint32(hdc, text, strlen(text), &sz); + + if(width) + *width = sz.cx; + + if(height) + *height = sz.cy; + + SelectObject(hdc, oldFont); + if(mustdelete) + DeleteObject(hFont); + if(!pixmap) + ReleaseDC(handle, hdc); +} + +/* Call this after drawing to the screen to make sure + * anything you have drawn is visible. + */ +void API dw_flush(void) +{ +} + +/* + * Creates a pixmap with given parameters. + * Parameters: + * handle: Window handle the pixmap is associated with. + * width: Width of the pixmap in pixels. + * height: Height of the pixmap in pixels. + * depth: Color depth of the pixmap. + * Returns: + * A handle to a pixmap or NULL on failure. + */ +HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth) +{ + HPIXMAP pixmap; + HDC hdc; + COLORREF bkcolor; + ULONG cx, cy; + + if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) + return NULL; + + hdc = GetDC(handle); + + pixmap->width = width; pixmap->height = height; + + pixmap->handle = handle; + pixmap->hbm = CreateCompatibleBitmap(hdc, width, height); + pixmap->hdc = CreateCompatibleDC(hdc); + pixmap->transcolor = DW_RGB_TRANSPARENT; + + SelectObject(pixmap->hdc, pixmap->hbm); + + ReleaseDC(handle, hdc); + + return pixmap; +} + +#ifndef GDIPLUS +/* Read the file bitmap header ourselves... + * apparently we can't check the depth once loaded... + * since it seems to normalize it to our screen depth. + */ +unsigned long _read_bitmap_header(char *file) +{ + BITMAPFILEHEADER header; + BITMAPINFO *info; + FILE *fp; + int infosize; + int depth = 0; + + /* Try opening the file; use "rb" mode to read this *binary* file. */ + if((fp = fopen(file, "rb")) == NULL) + return 0; + + /* Read the file header and any following bitmap information... */ + if(fread(&header, sizeof(BITMAPFILEHEADER), 1, fp) < 1) + { + /* Couldn't read the file header */ + fclose(fp); + return 0; + } + + if(header.bfType != 'MB') /* Check for BM reversed... */ + { + /* Not a bitmap file */ + fclose(fp); + return 0; + } + + infosize = header.bfOffBits - sizeof(BITMAPFILEHEADER); + if((info = (BITMAPINFO *)calloc(infosize, 1)) == NULL) + { + /* Couldn't allocate memory for bitmap info */ + fclose(fp); + return 0; + } + + if(fread(info, 1, infosize, fp) == infosize) + { + /* Read the bitmap header */ + depth = info->bmiHeader.biBitCount; + } + free(info); + fclose(fp); + return depth; +} +#endif + +/* + * Creates a pixmap from a file. + * Parameters: + * handle: Window handle the pixmap is associated with. + * filename: Name of the file, omit extention to have + * DW pick the appropriate file extension. + * (BMP on OS/2 or Windows, XPM on Unix) + * Returns: + * A handle to a pixmap or NULL on failure. + */ +HPIXMAP API dw_pixmap_new_from_file(HWND handle, char *filename) +{ + HPIXMAP pixmap; + BITMAP bm; + HDC hdc; + ULONG cx, cy; + BITMAPINFO *info; +#ifndef GDIPLUS + char *file; +#endif + + if (!filename || !(pixmap = calloc(1,sizeof(struct _hpixmap)))) + return NULL; + +#ifdef GDIPLUS + pixmap->hbm = _dw_load_bitmap(filename, &pixmap->depth); +#else + file = _alloca(strlen(filename) + 5); + strcpy(file, filename); + + /* check if we can read from this file (it exists and read permission) */ + if(access(file, 04) != 0) + { + /* Try with .bmp extention */ + strcat(file, ".bmp"); + if(access(file, 04) != 0) + { + free(pixmap); + free(file); + return NULL; + } + } + + pixmap->hbm = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + pixmap->depth = _read_bitmap_header(file); +#endif + + pixmap->handle = handle; + + if ( !pixmap->hbm ) + { + free(pixmap); + return NULL; + } + + hdc = GetDC(handle); + + pixmap->hdc = CreateCompatibleDC( hdc ); + GetObject( pixmap->hbm, sizeof(bm), &bm ); + pixmap->width = bm.bmWidth; pixmap->height = bm.bmHeight; + SelectObject( pixmap->hdc, pixmap->hbm ); + ReleaseDC( handle, hdc ); + pixmap->transcolor = DW_RGB_TRANSPARENT; + + return pixmap; +} + +/* + * Creates a pixmap from memory. + * Parameters: + * handle: Window handle the pixmap is associated with. + * data: Source of the image data + * (BMP on OS/2 or Windows, XPM on Unix) + * le: length of data + * Returns: + * A handle to a pixmap or NULL on failure. + */ +HPIXMAP API dw_pixmap_new_from_data(HWND handle, char *data, int len) +{ + HPIXMAP pixmap; + BITMAP bm; + HDC hdc; + char *file; + FILE *fp; + ULONG cx, cy; + + if ( !(pixmap = calloc(1,sizeof(struct _hpixmap))) ) + { + return NULL; + } + + hdc = GetDC(handle); + + pixmap->handle = handle; + + file = _tempnam( _dw_alternate_temp_dir, "dw" ); + if ( file != NULL ) + { + fp = fopen( file, "wb" ); + if ( fp != NULL ) + { + fwrite( data, 1, len, fp ); + fclose( fp ); +#ifdef GDIPLUS + pixmap->hbm = _dw_load_bitmap(file, NULL); +#else + pixmap->hbm = (HBITMAP)LoadImage( NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE ); + pixmap->depth = _read_bitmap_header(file); +#endif + } + else + { + unlink( file ); + free( file ); + free( pixmap ); + return NULL; + } + unlink( file ); + free( file ); + } + + if ( !pixmap->hbm ) + { + free( pixmap ); + ReleaseDC( handle, hdc ); + return NULL; + } + + pixmap->hdc = CreateCompatibleDC( hdc ); + + GetObject( pixmap->hbm, sizeof(bm), &bm ); + + pixmap->width = bm.bmWidth; pixmap->height = bm.bmHeight; + + SelectObject( pixmap->hdc, pixmap->hbm ); + + ReleaseDC( handle, hdc ); + pixmap->transcolor = DW_RGB_TRANSPARENT; + + return pixmap; +} + +/* + * Creates a bitmap mask for rendering bitmaps with transparent backgrounds + */ +void API dw_pixmap_set_transparent_color( HPIXMAP pixmap, ULONG color ) +{ + if ( pixmap && pixmap->depth < 32) + { + pixmap->transcolor = _internal_color(color); + } +} + +/* + * Creates a pixmap from internal resource graphic specified by id. + * Parameters: + * handle: Window handle the pixmap is associated with. + * id: Resource ID associated with requested pixmap. + * Returns: + * A handle to a pixmap or NULL on failure. + */ +HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id) +{ + HPIXMAP pixmap; + BITMAP bm; + HDC hdc; + + if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) + return NULL; + + hdc = GetDC(handle); + + pixmap->hbm = LoadBitmap(DWInstance, MAKEINTRESOURCE(id)); + pixmap->hdc = CreateCompatibleDC(hdc); + + GetObject(pixmap->hbm, sizeof(BITMAP), (void *)&bm); + + pixmap->width = bm.bmWidth; pixmap->height = bm.bmHeight; + pixmap->depth = bm.bmBitsPixel; + + SelectObject(pixmap->hdc, pixmap->hbm); + + ReleaseDC(handle, hdc); + pixmap->transcolor = DW_RGB_TRANSPARENT; + + return pixmap; +} + +/* + * Sets the font used by a specified pixmap. + * Normally the pixmap font is obtained from the associated window handle. + * However this can be used to override that, or for pixmaps with no window. + * Parameters: + * pixmap: Handle to a pixmap returned by dw_pixmap_new() or + * passed to the application via a callback. + * fontname: Name and size of the font in the form "size.fontname" + * Returns: + * DW_ERROR_NONE on success and DW_ERROR_GENERAL on failure. + */ +int API dw_pixmap_set_font(HPIXMAP pixmap, char *fontname) +{ + if(pixmap) + { + HFONT hfont = _acquire_font2(pixmap->hdc, fontname); + + if(hfont) + { + HFONT oldfont = pixmap->font; + pixmap->font = hfont; + if(oldfont) + DeleteObject(oldfont); + return DW_ERROR_NONE; + } + } + return DW_ERROR_GENERAL; +} + +/* + * Destroys an allocated pixmap. + * Parameters: + * pixmap: Handle to a pixmap returned by + * dw_pixmap_new.. + */ +void API dw_pixmap_destroy(HPIXMAP pixmap) +{ + if(pixmap) + { + DeleteDC(pixmap->hdc); + DeleteObject(pixmap->hbm); + if(pixmap->font) + DeleteObject(pixmap->font); + free(pixmap); + } +} + +/* + * Copies from one item to another. + * Parameters: + * dest: Destination window handle. + * destp: Destination pixmap. (choose only one). + * xdest: X coordinate of destination. + * ydest: Y coordinate of destination. + * width: Width of area to copy. + * height: Height of area to copy. + * src: Source window handle. + * srcp: Source pixmap. (choose only one). + * xsrc: X coordinate of source. + * ysrc: Y coordinate of source. + */ +void API dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc) +{ + dw_pixmap_stretch_bitblt(dest, destp, xdest, ydest, width, height, src, srcp, xsrc, ysrc, -1, -1); +} + +/* + * Copies from one surface to another allowing for stretching. + * Parameters: + * dest: Destination window handle. + * destp: Destination pixmap. (choose only one). + * xdest: X coordinate of destination. + * ydest: Y coordinate of destination. + * width: Width of the target area. + * height: Height of the target area. + * src: Source window handle. + * srcp: Source pixmap. (choose only one). + * xsrc: X coordinate of source. + * ysrc: Y coordinate of source. + * srcwidth: Width of area to copy. + * srcheight: Height of area to copy. + * Returns: + * DW_ERROR_NONE on success and DW_ERROR_GENERAL on failure. + */ +int API dw_pixmap_stretch_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc, int srcwidth, int srcheight) +{ + HDC hdcdest; + HDC hdcsrc; + static BLENDFUNCTION bf = { AC_SRC_OVER, 0, 0xFF, AC_SRC_ALPHA }; + int swidth = srcwidth, sheight = srcheight; + + /* Do some sanity checks */ + if ( dest ) + hdcdest = GetDC( dest ); + else if ( destp ) + hdcdest = destp->hdc; + else + return DW_ERROR_GENERAL; + + if ( src ) + hdcsrc = GetDC( src ); + else if ( srcp ) + hdcsrc = srcp->hdc; + else + return DW_ERROR_GENERAL; + + if((srcheight == -1 || srcwidth == -1) && srcheight != srcwidth) + return DW_ERROR_GENERAL; + + if(srcheight == -1 && srcwidth == -1) + { + swidth = width; + sheight = height; + } + + /* If it is a 32bpp bitmap (with alpha) use AlphaBlend unless it fails */ + if ( srcp && srcp->depth == 32 && AlphaBlend( hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, swidth, sheight, bf ) ) + { + /* Don't do anything */ + } + /* Otherwise perform special bitblt with manual transparency */ + else if ( srcp && srcp->transcolor != DW_RGB_TRANSPARENT ) + { + TransparentBlt( hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, swidth, sheight, RGB( DW_RED_VALUE(srcp->transcolor), DW_GREEN_VALUE(srcp->transcolor), DW_BLUE_VALUE(srcp->transcolor)) ); + } + else + { + /* Finally fall back to the classic BitBlt */ + if( srcwidth == -1 && srcheight == -1) + BitBlt( hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, SRCCOPY ); + else + StretchBlt( hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, swidth, sheight, SRCCOPY ); + } + if ( !destp ) + ReleaseDC( dest, hdcdest ); + if ( !srcp ) + ReleaseDC( src, hdcsrc ); + + return DW_ERROR_NONE; +} + +/* Run Beep() in a separate thread so it doesn't block */ +void _beepthread(void *data) +{ + int *info = (int *)data; + + if(data) + { + Beep(info[0], info[1]); + free(data); + } +} + +/* + * Emits a beep. + * Parameters: + * freq: Frequency. + * dur: Duration. + */ +void API dw_beep(int freq, int dur) +{ + int *info = malloc(sizeof(int) * 2); + + if(info) + { + info[0] = freq; + info[1] = dur; + + _beginthread(_beepthread, 100, (void *)info); + } +} + +/* Open a shared library and return a handle. + * Parameters: + * name: Base name of the shared library. + * handle: Pointer to a module handle, + * will be filled in with the handle. + */ +int API dw_module_load(char *name, HMOD *handle) +{ + if(!handle) + return DW_ERROR_UNKNOWN; + + *handle = LoadLibrary(name); + return (NULL == *handle); +} + +/* Queries the address of a symbol within open handle. + * Parameters: + * handle: Module handle returned by dw_module_load() + * name: Name of the symbol you want the address of. + * func: A pointer to a function pointer, to obtain + * the address. + */ +int API dw_module_symbol(HMOD handle, char *name, void**func) +{ + if(!func || !name) + return DW_ERROR_UNKNOWN; + + if(0 == strlen(name)) + return DW_ERROR_UNKNOWN; + + *func = (void*)GetProcAddress(handle, name); + return (NULL == *func); +} + +/* Frees the shared library previously opened. + * Parameters: + * handle: Module handle returned by dw_module_load() + */ +int API dw_module_close(HMOD handle) +{ + return FreeLibrary(handle); +} + +/* + * Returns the handle to an unnamed mutex semaphore. + */ +HMTX API dw_mutex_new(void) +{ + return (HMTX)CreateMutex(NULL, FALSE, NULL); +} + +/* + * Closes a semaphore created by dw_mutex_new(). + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + */ +void API dw_mutex_close(HMTX mutex) +{ + CloseHandle((HANDLE)mutex); +} + +/* + * Tries to gain access to the semaphore, if it can't it blocks. + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + */ +void API dw_mutex_lock(HMTX mutex) +{ + if(_dwtid == dw_thread_id()) + { + int rc = WaitForSingleObject((HANDLE)mutex, 0); + + while(rc == WAIT_TIMEOUT) + { + dw_main_sleep(1); + rc = WaitForSingleObject((HANDLE)mutex, 0); + } + } + else + WaitForSingleObject((HANDLE)mutex, INFINITE); +} + +/* + * Tries to gain access to the semaphore. + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + * Returns: + * DW_ERROR_NONE on success, DW_ERROR_TIMEOUT if it is already locked. + */ +int API dw_mutex_trylock(HMTX mutex) +{ + if(WaitForSingleObject((HANDLE)mutex, 0) == WAIT_OBJECT_0) + return DW_ERROR_NONE; + return DW_ERROR_TIMEOUT; +} + +/* + * Reliquishes the access to the semaphore. + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + */ +void API dw_mutex_unlock(HMTX mutex) +{ + ReleaseMutex((HANDLE)mutex); +} + +/* + * Returns the handle to an unnamed event semaphore. + */ +HEV API dw_event_new(void) +{ + return CreateEvent(NULL, TRUE, FALSE, NULL); +} + +/* + * Resets a semaphore created by dw_event_new(). + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int API dw_event_reset(HEV eve) +{ + if(ResetEvent(eve)) + return DW_ERROR_NONE; + return DW_ERROR_GENERAL; +} + +/* + * Posts a semaphore created by dw_event_new(). Causing all threads + * waiting on this event in dw_event_wait to continue. + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int API dw_event_post(HEV eve) +{ + if(SetEvent(eve)) + return DW_ERROR_NONE; + return DW_ERROR_GENERAL; +} + +/* + * Waits on a semaphore created by dw_event_new(), until the + * event gets posted or until the timeout expires. + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int API dw_event_wait(HEV eve, unsigned long timeout) +{ + int rc; + + rc = WaitForSingleObject(eve, timeout != -1 ? timeout : INFINITE); + if(rc == WAIT_OBJECT_0) + return DW_ERROR_NONE; + if(rc == WAIT_TIMEOUT) + return DW_ERROR_TIMEOUT; + if(rc == WAIT_ABANDONED) + return DW_ERROR_INTERRUPT; + return DW_ERROR_GENERAL; +} + +/* + * Closes a semaphore created by dw_event_new(). + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int API dw_event_close(HEV *eve) +{ + if(eve && CloseHandle(*eve)) + return DW_ERROR_NONE; + return DW_ERROR_GENERAL; +} + +/* Create a named event semaphore which can be + * opened from other processes. + * Parameters: + * eve: Pointer to an event handle to receive handle. + * name: Name given to semaphore which can be opened + * by other processes. + */ +HEV API dw_named_event_new(char *name) +{ + SECURITY_ATTRIBUTES sa; + + sa.nLength = sizeof( SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = &_dwsd; + sa.bInheritHandle = FALSE; + + return CreateEvent(&sa, TRUE, FALSE, name); +} + +/* Destroy this semaphore. + * Parameters: + * eve: Handle to the semaphore obtained by + * a create call. + */ +HEV API dw_named_event_get(char *name) +{ + return OpenEvent(EVENT_ALL_ACCESS, FALSE, name); +} + +/* Resets the event semaphore so threads who call wait + * on this semaphore will block. + * Parameters: + * eve: Handle to the semaphore obtained by + * an open or create call. + */ +int API dw_named_event_reset(HEV eve) +{ + if(ResetEvent(eve)) + return DW_ERROR_NONE; + return DW_ERROR_GENERAL; +} + +/* Sets the posted state of an event semaphore, any threads + * waiting on the semaphore will no longer block. + * Parameters: + * eve: Handle to the semaphore obtained by + * an open or create call. + */ +int API dw_named_event_post(HEV eve) +{ + if(SetEvent(eve)) + return DW_ERROR_NONE; + return DW_ERROR_GENERAL; +} + +/* Waits on the specified semaphore until it becomes + * posted, or returns immediately if it already is posted. + * Parameters: + * eve: Handle to the semaphore obtained by + * an open or create call. + * timeout: Number of milliseconds before timing out + * or -1 if indefinite. + */ +int API dw_named_event_wait(HEV eve, unsigned long timeout) +{ + int rc; + + rc = WaitForSingleObject(eve, timeout != -1 ? timeout : INFINITE); + if(rc == WAIT_OBJECT_0) + return DW_ERROR_NONE; + if(rc == WAIT_TIMEOUT) + return DW_ERROR_TIMEOUT; + if(rc == WAIT_ABANDONED) + return DW_ERROR_INTERRUPT; + return DW_ERROR_GENERAL; +} + +/* Release this semaphore, if there are no more open + * handles on this semaphore the semaphore will be destroyed. + * Parameters: + * eve: Handle to the semaphore obtained by + * an open or create call. + */ +int API dw_named_event_close(HEV eve) +{ + if(CloseHandle(eve)) + return DW_ERROR_NONE; + return DW_ERROR_GENERAL; +} + +/* + * Allocates a shared memory region with a name. + * Parameters: + * handle: A pointer to receive a SHM identifier. + * dest: A pointer to a pointer to receive the memory address. + * size: Size in bytes of the shared memory region to allocate. + * name: A string pointer to a unique memory name. + */ +HSHM API dw_named_memory_new(void **dest, int size, char *name) +{ + SECURITY_ATTRIBUTES sa; + HSHM handle; + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = &_dwsd; + sa.bInheritHandle = FALSE; + + handle = CreateFileMapping((HANDLE)0xFFFFFFFF, &sa, PAGE_READWRITE, 0, size, name); + + if(!handle) + return 0; + + *dest = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0); + + if(!*dest) + { + CloseHandle(handle); + return 0; + } + + return handle; +} + +/* + * Aquires shared memory region with a name. + * Parameters: + * dest: A pointer to a pointer to receive the memory address. + * size: Size in bytes of the shared memory region to requested. + * name: A string pointer to a unique memory name. + */ +HSHM API dw_named_memory_get(void **dest, int size, char *name) +{ + HSHM handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name); + + if(!handle) + return 0; + + *dest = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0); + + if(!*dest) + { + CloseHandle(handle); + return 0; + } + + return handle; +} + +/* + * Frees a shared memory region previously allocated. + * Parameters: + * handle: Handle obtained from DB_named_memory_allocate. + * ptr: The memory address aquired with DB_named_memory_allocate. + */ +int API dw_named_memory_free(HSHM handle, void *ptr) +{ + UnmapViewOfFile(ptr); + CloseHandle(handle); + return 0; +} + +/* + * Encapsulate thread creation on Win32. + */ +void _dwthreadstart(void *data) +{ + void (* threadfunc)(void *) = NULL; + void **tmp = (void **)data; + HPEN hPen; + HBRUSH hBrush; + + _init_thread(); + + threadfunc = (void (*)(void *))tmp[0]; + threadfunc(tmp[1]); + + free(tmp); + if((hPen = TlsGetValue(_hPen))) + DeleteObject(hPen); + if((hBrush = TlsGetValue(_hBrush))) + DeleteObject(hBrush); +} + +/* + * Creates a new thread with a starting point of func. + * Parameters: + * func: Function which will be run in the new thread. + * data: Parameter(s) passed to the function. + * stack: Stack size of new thread (OS/2 and Windows only). + */ +DWTID API dw_thread_new(void *func, void *data, int stack) +{ +#if defined(__CYGWIN__) + return 0; +#else + void **tmp = malloc(sizeof(void *) * 2); + + tmp[0] = func; + tmp[1] = data; + + return (DWTID)_beginthread((void(*)(void *))_dwthreadstart, stack, tmp); +#endif +} + +/* + * Ends execution of current thread immediately. + */ +void API dw_thread_end(void) +{ +#if !defined(__CYGWIN__) + _endthread(); +#endif +} + +/* + * Returns the current thread's ID. + */ +DWTID API dw_thread_id(void) +{ +#if defined(__CYGWIN__) + return 0; +#else + return (DWTID)GetCurrentThreadId(); +#endif +} + +/* + * 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) +{ + OleUninitialize(); + exit(exitcode); +} + +/* + * Creates a splitbar window (widget) with given parameters. + * Parameters: + * type: Value can be DW_VERT or DW_HORZ. + * topleft: Handle to the window to be top or left. + * bottomright: Handle to the window to be bottom or right. + * Returns: + * A handle to a splitbar window or NULL on failure. + */ +HWND API dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id) +{ + HWND tmp = CreateWindow(SplitbarClassName, + "", + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, + 0,0,2000,1000, + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + + if(tmp) + { + HWND tmpbox = dw_box_new(DW_VERT, 0); + 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); + + 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); + *percent = 50.0; + dw_window_set_data(tmp, "_dw_percent", (void *)percent); + dw_window_set_data(tmp, "_dw_type", (void *)type); + } + return tmp; +} + +/* + * Sets the position of a splitbar (pecentage). + * Parameters: + * handle: The handle to the splitbar returned by dw_splitbar_new(). + */ +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; + + if(mypercent) + *mypercent = percent; + + dw_window_get_pos_size(handle, NULL, NULL, &width, &height); + + _handle_splitbar_resize(handle, percent, type, width, height); +} + +/* + * Gets the position of a splitbar (pecentage). + * Parameters: + * handle: The handle to the splitbar returned by dw_splitbar_new(). + */ +float API dw_splitbar_get(HWND handle) +{ + float *percent = (float *)dw_window_get_data(handle, "_dw_percent"); + + if(percent) + return *percent; + return 0.0; +} + +/* + * Creates a calendar window (widget) with given parameters. + * Parameters: + * type: Value can be DW_VERT or DW_HORZ. + * topleft: Handle to the window to be top or left. + * bottomright: Handle to the window to be bottom or right. + * Classname: SysMonthCal32 + * Returns: + * A handle to a calendar window or NULL on failure. + */ +HWND API dw_calendar_new(unsigned long id) +{ + RECT rc; + MONTHDAYSTATE mds[3]; + HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE, + MONTHCAL_CLASS, + "", + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | MCS_DAYSTATE, + 0,0,2000,1000, // resize it later + DW_HWND_OBJECT, + (HMENU)id, + DWInstance, + NULL); + if ( tmp ) + { + // Get the size required to show an entire month. + MonthCal_GetMinReqRect(tmp, &rc); + // Resize the control now that the size values have been obtained. + SetWindowPos(tmp, NULL, 0, 0, + rc.right, rc.bottom, + SWP_NOZORDER | SWP_NOMOVE); + mds[0] = mds[1] = mds[2] = (MONTHDAYSTATE)0; + MonthCal_SetDayState(tmp,3,mds); + return tmp; + } + else + return NULL; +} + +/* + * Sets the current date of a calendar + * Parameters: + * handle: The handle to the calendar returned by dw_calendar_new(). + * year: The year to set the date to + * month: The month to set the date to + * day: The day to set the date to + */ +void API dw_calendar_set_date(HWND handle, unsigned int year, unsigned int month, unsigned int day) +{ + MONTHDAYSTATE mds[3]; + SYSTEMTIME date; + date.wYear = year; + date.wMonth = month; + date.wDay = day; + if ( MonthCal_SetCurSel( handle, &date ) ) + { + } + else + { + } + mds[0] = mds[1] = mds[2] = (MONTHDAYSTATE)0; + MonthCal_SetDayState(handle,3,mds); +} + +/* + * Gets the date from the calendar + * Parameters: + * handle: The handle to the calendar returned by dw_calendar_new(). + * year: Pointer to the year to get the date to + * month: Pointer to the month to get the date to + * day: Pointer to the day to get the date to + */ +void API dw_calendar_get_date(HWND handle, unsigned int *year, unsigned int *month, unsigned int *day) +{ + SYSTEMTIME date; + if ( MonthCal_GetCurSel( handle, &date ) ) + { + *year = date.wYear; + *month = date.wMonth; + *day = date.wDay; + } + else + { + *year = *month = *day = 0; + } +} + +/* + * Sets the default focus item for a window/dialog. + * Parameters: + * window: Toplevel window or dialog. + * defaultitem: Handle to the dialog item to be default. + */ +void API dw_window_default(HWND window, HWND defaultitem) +{ + Box *thisbox = (Box *)GetWindowLongPtr(window, GWLP_USERDATA); + + if(thisbox) + thisbox->defaultitem = defaultitem; +} + +/* + * Sets window to click the default dialog item when an ENTER is pressed. + * Parameters: + * window: Window (widget) to look for the ENTER press. + * next: Window (widget) to move to next (or click) + */ +void API dw_window_click_default(HWND window, HWND next) +{ + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(window, GWLP_USERDATA); + + if (cinfo) + { + cinfo->clickdefault = next; + } +} + +/* + * Gets the contents of the default clipboard as text. + * Parameters: + * None. + * Returns: + * Pointer to an allocated string of text or NULL if clipboard empty or contents could not + * be converted to text. + */ +char *dw_clipboard_get_text() +{ + HANDLE handle; + char *tmp, *ret = NULL; + + if ( !OpenClipboard( NULL ) ) + return ret; + + if ( ( handle = GetClipboardData( CF_TEXT) ) == NULL ) + { + CloseClipboard(); + return ret; + } + + if ( (tmp = GlobalLock(handle)) && strlen(tmp) ) + { + ret = strdup(tmp); + GlobalUnlock(handle); + } + CloseClipboard(); + return ret; +} + +/* + * Sets the contents of the default clipboard to the supplied text. + * Parameters: + * Text. + */ +void dw_clipboard_set_text( char *str, int len ) +{ + HGLOBAL ptr1; + LPTSTR ptr2; + + if ( !OpenClipboard( NULL ) ) + return; + + ptr1 = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, (len + 1) * sizeof(TCHAR) ); + + if ( !ptr1 ) + return; + + ptr2 = GlobalLock( ptr1 ); + + memcpy( (char *)ptr2, str, len + 1); + GlobalUnlock( ptr1 ); + EmptyClipboard(); + + SetClipboardData( CF_TEXT, ptr1 ); + + CloseClipboard(); + GlobalFree( ptr1 ); + + return; +} + +/* + * Returns some information about the current operating environment. + * Parameters: + * env: Pointer to a DWEnv struct. + */ +void API dw_environment_query(DWEnv *env) +{ + if(!env) + return; + + /* Get the Windows version. */ + + env->MajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); + env->MinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); + + /* Get the build number for Windows NT/Windows 2000. */ + + env->MinorBuild = 0; + + if (dwVersion < 0x80000000) + { + if(env->MajorVersion == 5 && env->MinorVersion == 0) + strcpy(env->osName, "Windows 2000"); + else if(env->MajorVersion == 5 && env->MinorVersion > 0) + strcpy(env->osName, "Windows XP"); + else if(env->MajorVersion == 6 && env->MinorVersion == 0) + strcpy(env->osName, "Windows Vista"); + else if(env->MajorVersion == 6 && env->MinorVersion > 0) + strcpy(env->osName, "Windows 7"); + else + strcpy(env->osName, "Windows NT"); + + env->MajorBuild = (DWORD)(HIWORD(dwVersion)); + } + else + { + strcpy(env->osName, "Windows 95/98/ME"); + env->MajorBuild = 0; + } + + strcpy(env->buildDate, __DATE__); + strcpy(env->buildTime, __TIME__); + env->DWMajorVersion = DW_MAJOR_VERSION; + env->DWMinorVersion = DW_MINOR_VERSION; +#ifdef VER_REV + env->DWSubVersion = VER_REV; +#else + env->DWSubVersion = DW_SUB_VERSION; +#endif +} + +/* Helper to make sure all /s are \s */ +void _to_dos(char *dst, char *src) +{ + int x = 0; + + while(src[x]) + { + if(src[x] == '/') + dst[x] = '\\'; + else + dst[x] = src[x]; + x++; + } + dst[x] = 0; +} + +/* + * Opens a file dialog and queries user selection. + * Parameters: + * title: Title bar text for dialog. + * defpath: The default path of the open dialog. + * ext: Default file extention. + * flags: DW_FILE_OPEN or DW_FILE_SAVE or DW_DIRECTORY_OPEN. + * Returns: + * NULL on error. A malloced buffer containing + * the file path on success. + * + */ +char * API dw_file_browse(char *title, char *defpath, char *ext, int flags) +{ + OPENFILENAME of; + char filenamebuf[1001] = {0}; + char filterbuf[1001] = {0}; + int rc; + + BROWSEINFO bi; + TCHAR szDir[MAX_PATH]; + LPITEMIDLIST pidl; + LPMALLOC pMalloc; + + if ( flags == DW_DIRECTORY_OPEN ) + { + /* If we aren't building a DLL, use the more simple browser */ +#ifndef BUILD_DLL + if (SUCCEEDED(SHGetMalloc(&pMalloc))) + { + ZeroMemory(&bi,sizeof(bi)); + bi.hwndOwner = NULL; + bi.pszDisplayName = 0; + bi.pidlRoot = 0; + bi.lpszTitle = title; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT; + bi.lpfn = NULL; /*BrowseCallbackProc*/ + + pidl = SHBrowseForFolder(&bi); + if (pidl) + { + if (SHGetPathFromIDList(pidl,szDir)) + { + strncpy(filenamebuf,szDir,1000); + } + + // In C++: pMalloc->Free(pidl); pMalloc->Release(); + pMalloc->lpVtbl->Free(pMalloc,pidl); + pMalloc->lpVtbl->Release(pMalloc); + return strdup(filenamebuf); + } + } +#else + if ( XBrowseForFolder( NULL, + (LPCTSTR)defpath, + -1, + (LPCTSTR)title, + (LPTSTR)filenamebuf, + 1000, + FALSE ) ) + { + return strdup( filenamebuf ); + } +#endif + } + else + { + DWORD att = defpath ? GetFileAttributes(defpath) : INVALID_FILE_ATTRIBUTES; + + if (ext) + { + /* + * The following mess is because sprintf() trunates at first \0 + * and format of filter is eg: "c files (*.c)\0*.c\0All Files\0*.*\0\0" + */ + int len; + char *ptr = filterbuf; + memset( filterbuf, 0, sizeof(filterbuf) ); + len = sprintf( ptr, "%s Files (*.%s)", ext, ext ); + ptr = ptr + len + 1; // past first \0 + len = sprintf( ptr, "*.%s", ext ); + ptr = ptr + len + 1; // past next \0 + len = sprintf( ptr, "All Files" ); + ptr = ptr + len + 1; // past next \0 + len = sprintf( ptr, "*.*" ); + } + + memset( &of, 0, sizeof(OPENFILENAME) ); + + of.lStructSize = sizeof(OPENFILENAME); + of.hwndOwner = HWND_DESKTOP; + of.hInstance = DWInstance; + of.lpstrTitle = title; + of.lpstrInitialDir = "."; + if(att != INVALID_FILE_ATTRIBUTES && (att & FILE_ATTRIBUTE_DIRECTORY)) + of.lpstrInitialDir = defpath; + else if(defpath) + _to_dos(filenamebuf, defpath); + of.lpstrFile = filenamebuf; + of.lpstrFilter = filterbuf; + of.nFilterIndex = 1; + of.nMaxFile = 1000; + /*of.lpstrDefExt = ext;*/ + of.Flags = OFN_NOCHANGEDIR; + + if (flags & DW_FILE_SAVE) + { + of.Flags |= OFN_OVERWRITEPROMPT; + rc = GetSaveFileName(&of); + } + else + { + of.Flags |= OFN_FILEMUSTEXIST; + rc = GetOpenFileName(&of); + } + + if (rc) + return strdup(of.lpstrFile); + } + return NULL; +} + +/* + * Execute and external program in a seperate session. + * Parameters: + * program: Program name with optional path. + * type: Either DW_EXEC_CON or DW_EXEC_GUI. + * params: An array of pointers to string arguements. + * Returns: + * -1 on error. + */ +int API dw_exec(char *program, int type, char **params) +{ + char **newparams; + int retcode, count = 0, z; + + while(params[count]) + { + count++; + } + + newparams = (char **)malloc(sizeof(char *) * (count+1)); + + for(z=0;z<count;z++) + { + newparams[z] = malloc(strlen(params[z])+3); + strcpy(newparams[z], "\""); + strcat(newparams[z], params[z]); + strcat(newparams[z], "\""); + } + newparams[count] = NULL; + + retcode = spawnvp(P_NOWAIT, program, newparams); + + for(z=0;z<count;z++) + { + free(newparams[z]); + } + free(newparams); + + return retcode; +} + +/* + * Loads a web browser pointed at the given URL. + * Parameters: + * url: Uniform resource locator. + */ +int API dw_browse(char *url) +{ + char *browseurl = url; + int retcode; + + if(strlen(url) > 7 && strncmp(url, "file://", 7) == 0) + { + int len, z; + + browseurl = &url[7]; + len = strlen(browseurl); + + for(z=0;z<len;z++) + { + if(browseurl[z] == '|') + browseurl[z] = ':'; + if(browseurl[z] == '/') + browseurl[z] = '\\'; + } + } + + retcode = (int)ShellExecute(NULL, "open", browseurl, NULL, NULL, SW_SHOWNORMAL); + if(retcode<33 && retcode != 2) + return DW_ERROR_UNKNOWN; + return DW_ERROR_NONE; +} + +typedef struct _dwprint +{ + PRINTDLG pd; + DOCINFO di; + int (*drawfunc)(HPRINT, HPIXMAP, int, void *); + void *drawdata; + unsigned long flags; +} DWPrint; + +/* + * Creates a new print object. + * Parameters: + * jobname: Name of the print job to show in the queue. + * flags: Flags to initially configure the print object. + * pages: Number of pages to print. + * drawfunc: The pointer to the function to be used as the callback. + * drawdata: User data to be passed to the handler function. + * Returns: + * A handle to the print object or NULL on failure. + */ +HPRINT API dw_print_new(char *jobname, unsigned long flags, unsigned int pages, void *drawfunc, void *drawdata) +{ + DWPrint *print; + + if(!drawfunc || !(print = calloc(1, sizeof(DWPrint)))) + return NULL; + + print->drawfunc = drawfunc; + print->drawdata = drawdata; + print->pd.lStructSize = sizeof(PRINTDLG); + print->pd.hwndOwner = HWND_DESKTOP; + print->pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC; + print->pd.nCopies = 1; + print->pd.nFromPage = 1; + print->pd.nToPage = pages; + print->pd.nMinPage = 1; + print->pd.nMaxPage = pages; + + if(!PrintDlg(&(print->pd))) + { + free(print); + return NULL; + } + + print->di.cbSize = sizeof(DOCINFO); + print->di.lpszDocName = jobname ? jobname : "Dynamic Windows Print Job"; + return print; +} + +/* + * Runs the print job, causing the draw page callbacks to fire. + * Parameters: + * print: Handle to the print object returned by dw_print_new(). + * flags: Flags to run the print job. + * Returns: + * DW_ERROR_UNKNOWN on error or DW_ERROR_NONE on success. + */ +int API dw_print_run(HPRINT print, unsigned long flags) +{ + DWPrint *p = print; + HPIXMAP pixmap; + int x, result = DW_ERROR_UNKNOWN; + + if(!p) + return result; + + if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) + return result; + + pixmap->width = GetDeviceCaps(p->pd.hDC, HORZRES); + pixmap->height = GetDeviceCaps(p->pd.hDC, VERTRES); + + pixmap->hbm = CreateCompatibleBitmap(p->pd.hDC, pixmap->width, pixmap->height); + pixmap->hdc = p->pd.hDC; + pixmap->transcolor = DW_RGB_TRANSPARENT; + + SelectObject(pixmap->hdc, pixmap->hbm); + + /* Start the job */ + StartDoc(p->pd.hDC, &(p->di)); + + /* Cycle through each page */ + for(x=p->pd.nFromPage-1; x<p->pd.nToPage && p->drawfunc; x++) + { + StartPage(p->pd.hDC); + p->drawfunc(print, pixmap, x, p->drawdata); + EndPage(p->pd.hDC); + } + EndDoc(p->pd.hDC); + if(p->drawfunc) + result = DW_ERROR_NONE; + /* Free memory */ + dw_pixmap_destroy(pixmap); + free(p); + return result; +} + +/* + * Cancels the print job, typically called from a draw page callback. + * Parameters: + * print: Handle to the print object returned by dw_print_new(). + */ +void API dw_print_cancel(HPRINT print) +{ + DWPrint *p = print; + + if(p) + p->drawfunc = NULL; +} + +/* + * Returns a pointer to a static buffer which containes the + * current user directory. Or the root directory (C:\ on + * OS/2 and Windows). + */ +char * API dw_user_dir(void) +{ + static char _user_dir[1024] = ""; + + if(!_user_dir[0]) + { + HANDLE hToken = 0; + + /* Use the Windows API to get the user's profile directory */ + if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + { + DWORD BufSize = 1024; + + GetUserProfileDirectory(hToken, _user_dir, &BufSize); + CloseHandle(hToken); + } + /* If it fails set it to the root directory */ + if(!_user_dir[0]) + { + strcpy(_user_dir, "C:\\"); + } + } + return _user_dir; +} + +/* + * Call a function from the window (widget)'s context. + * Parameters: + * handle: Window handle of the widget. + * function: Function pointer to be called. + * data: Pointer to the data to be passed to the function. + */ +void API dw_window_function(HWND handle, void *function, void *data) +{ + SendMessage(handle, WM_USER, (WPARAM)function, (LPARAM)data); +} + +/* Functions for managing the user data lists that are associated with + * a given window handle. Used in dw_window_set_data() and + * dw_window_get_data(). + */ +UserData *_find_userdata(UserData **root, char *varname) +{ + UserData *tmp = *root; + + while(tmp) + { + if(stricmp(tmp->varname, varname) == 0) + return tmp; + tmp = tmp->next; + } + return NULL; +} + +int _new_userdata(UserData **root, char *varname, void *data) +{ + UserData *new = _find_userdata(root, varname); + + if(new) + { + new->data = data; + return TRUE; + } + else + { + new = malloc(sizeof(UserData)); + if(new) + { + new->varname = strdup(varname); + new->data = data; + + new->next = NULL; + + if (!*root) + *root = new; + else + { + UserData *prev = *root, *tmp = prev->next; + + while(tmp) + { + prev = tmp; + tmp = tmp->next; + } + prev->next = new; + } + return TRUE; + } + } + return FALSE; +} + +int _remove_userdata(UserData **root, char *varname, int all) +{ + UserData *prev = NULL, *tmp = *root; + + while(tmp) + { + if(all || stricmp(tmp->varname, varname) == 0) + { + if(!prev) + { + *root = tmp->next; + free(tmp->varname); + free(tmp); + if(!all) + return 0; + tmp = *root; + } + else + { + /* If all is true we should + * never get here. + */ + prev->next = tmp->next; + free(tmp->varname); + free(tmp); + return 0; + } + } + else + { + prev = tmp; + tmp = tmp->next; + } + } + return 0; +} + +/* + * Add a named user data item to a window handle. + * Parameters: + * window: Window handle of signal to be called back. + * dataname: A string pointer identifying which signal to be hooked. + * data: User data to be passed to the handler function. + */ +void API dw_window_set_data(HWND window, char *dataname, void *data) +{ + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(window, GWLP_USERDATA); + + if(!cinfo) + { + if(!dataname) + return; + + cinfo = calloc(1, sizeof(ColorInfo)); + cinfo->fore = cinfo->back = -1; + SetWindowLongPtr(window, GWLP_USERDATA, (LONG_PTR)cinfo); + } + + if(cinfo) + { + if(data) + _new_userdata(&(cinfo->root), dataname, data); + else + { + if(dataname) + _remove_userdata(&(cinfo->root), dataname, FALSE); + else + _remove_userdata(&(cinfo->root), NULL, TRUE); + } + } +} + +/* + * Gets a named user data item to a window handle. + * Parameters: + * window: Window handle of signal to be called back. + * dataname: A string pointer identifying which signal to be hooked. + * data: User data to be passed to the handler function. + */ +void * API dw_window_get_data(HWND window, char *dataname) +{ + ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(window, GWLP_USERDATA); + + if(cinfo && cinfo->root && dataname) + { + UserData *ud = _find_userdata(&(cinfo->root), dataname); + if(ud) + return ud->data; + } + return NULL; +} + +/* + * Add a callback to a timer event. + * Parameters: + * interval: Milliseconds to delay between calls. + * sigfunc: The pointer to the function to be used as the callback. + * data: User data to be passed to the handler function. + * Returns: + * Timer ID for use with dw_timer_disconnect(), 0 on error. + */ +int API dw_timer_connect(int interval, void *sigfunc, void *data) +{ + if(sigfunc) + { + int timerid = SetTimer(NULL, 0, interval, _TimerProc); + + if(timerid) + { + _new_signal(WM_TIMER, NULL, timerid, sigfunc, data); + return timerid; + } + } + return 0; +} + +/* + * Removes timer callback. + * Parameters: + * id: Timer ID returned by dw_timer_connect(). + */ +void API dw_timer_disconnect(int id) +{ + SignalHandler *prev = NULL, *tmp = Root; + + /* 0 is an invalid timer ID */ + if(!id) + return; + + KillTimer(NULL, id); + + while(tmp) + { + if(tmp->id == id) + { + if(prev) + { + prev->next = tmp->next; + free(tmp); + tmp = prev->next; + } + else + { + Root = tmp->next; + free(tmp); + tmp = Root; + } + } + else + { + prev = tmp; + tmp = tmp->next; + } + } +} + +/* + * Add a callback to a window event. + * 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. + * data: User data to be passed to the handler function. + */ +void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data) +{ + ULONG message = 0, id = 0; + + if (window && signame && sigfunc) + { + if (stricmp(signame, DW_SIGNAL_SET_FOCUS) == 0) + window = _normalize_handle(window); + + if ((message = _findsigmessage(signame)) != 0) + { + /* Handle special case of the menu item */ + if (message == WM_COMMAND && window < (HWND)65536) + { + char buffer[16]; + HWND owner; + + _snprintf(buffer, 15, "_dw_id%d", (int)window); + owner = (HWND)dw_window_get_data(DW_HWND_OBJECT, buffer); + + /* Make sure there are no dupes from popups */ + dw_signal_disconnect_by_window(window); + + if (owner) + { + id = (ULONG)window; + window = owner; + } + } + _new_signal(message, window, id, sigfunc, data); + } + } +} + +/* + * Removes callbacks for a given window with given name. + * Parameters: + * window: Window handle of callback to be removed. + */ +void API dw_signal_disconnect_by_name(HWND window, char *signame) +{ + SignalHandler *prev = NULL, *tmp = Root; + ULONG message; + + if(!window || !signame || (message = _findsigmessage(signame)) == 0) + return; + + while(tmp) + { + if(((window < (HWND)65536 && (int)window == tmp->id) || tmp->window == window) && tmp->message == message) + { + if(prev) + { + prev->next = tmp->next; + free(tmp); + tmp = prev->next; + } + else + { + Root = tmp->next; + free(tmp); + tmp = Root; + } + } + else + { + prev = tmp; + tmp = tmp->next; + } + } +} + +/* + * Removes all callbacks for a given window. + * Parameters: + * window: Window handle of callback to be removed. + */ +void API dw_signal_disconnect_by_window(HWND window) +{ + SignalHandler *prev = NULL, *tmp = Root; + + while(tmp) + { + if((window < (HWND)65536 && (int)window == tmp->id) || tmp->window == window) + { + if(prev) + { + prev->next = tmp->next; + free(tmp); + tmp = prev->next; + } + else + { + Root = tmp->next; + free(tmp); + tmp = Root; + } + } + else + { + prev = tmp; + tmp = tmp->next; + } + } +} + +/* + * Removes all callbacks for a given window with specified data. + * Parameters: + * window: Window handle of callback to be removed. + * data: Pointer to the data to be compared against. + */ +void API dw_signal_disconnect_by_data(HWND window, void *data) +{ + SignalHandler *prev = NULL, *tmp = Root; + + while(tmp) + { + if(((window < (HWND)65536 && (int)window == tmp->id) || tmp->window == window) && tmp->data == data) + { + if(prev) + { + prev->next = tmp->next; + free(tmp); + tmp = prev->next; + } + else + { + Root = tmp->next; + free(tmp); + tmp = Root; + } + } + else + { + prev = tmp; + tmp = tmp->next; + } + } +}