1 /*
2  * Helper functions for filling in DLG(ITEM)TEMPLATEs -
3  * closely based on code provided Rector & Newcomer
4  * in their book, Win32 programming.
5  *
6  * The only change here is to make it possible to
7  * add any number of controls to the dialog without
8  * having to worry about overrunning the chunk of
9  * memory that we're writing all this info into.
10  *
11  */
12 
13 #define UNICODE
14 #include <windows.h>
15 #include <wchar.h>
16 #include <stdlib.h>
17 #include "diatemp.h"
18 
19 #define DLGTEMPLATE_WORKING_SIZE 4096
20 
getFinalDialog(DIA_TEMPLATE * dt)21 LPDLGTEMPLATE getFinalDialog(DIA_TEMPLATE* dt)
22 {
23   LPDLGTEMPLATE ptr = dt->dtemplate;
24   free(dt);
25   return ptr;
26 }
27 
28 LPWORD
appendString(LPWORD ptr,LPCWSTR text)29 appendString (LPWORD ptr, LPCWSTR text)
30 {
31  LPWSTR str = (LPWSTR)ptr;
32  wcscpy(str, text);
33  ptr = (LPWORD)(str + wcslen(str) + 1);
34  return ptr;
35 }
36 
37 LPWORD
setClassAtom(LPDLGITEMTEMPLATE item,WORD classatom)38 setClassAtom(LPDLGITEMTEMPLATE item, WORD classatom)
39 {
40   LPWORD ptr = (LPWORD)&item[1];
41   *ptr++ = 0xffff;
42   *ptr++ = classatom;
43   return ptr;
44 }
45 
46 LPWORD
setClassName(LPDLGITEMTEMPLATE item,LPCWSTR classname)47 setClassName(LPDLGITEMTEMPLATE item, LPCWSTR classname)
48 {
49   LPWORD ptr = (LPWORD)&item[1];
50   ptr = appendString(ptr, classname);
51   return ptr;
52 }
53 
54 LPWORD
setResourceID(LPWORD ptr,WORD id)55 setResourceID(LPWORD ptr, WORD id)
56 {
57  *ptr++ = 0xffff;
58  *ptr++ = (WORD)id;
59  return ptr;
60 }
61 
62 DIA_TEMPLATE*
mkDiaTemplate(UINT size,int x,int y,int cx,int cy,DWORD style,DWORD exstyle,LPCWSTR menu,LPCWSTR class,LPCWSTR caption,LPCWSTR font,int height)63 mkDiaTemplate
64       ( UINT size, int x, int y, int cx, int cy
65       , DWORD style, DWORD exstyle
66       , LPCWSTR menu, LPCWSTR class
67       , LPCWSTR caption, LPCWSTR font
68       , int height
69       )
70 {
71   LPDLGTEMPLATE dlg;
72   LPWORD ptr;
73   DIA_TEMPLATE* dtemp;
74 
75   if ( size == 0 ) {
76      size = DLGTEMPLATE_WORKING_SIZE;
77   }
78   dlg = (LPDLGTEMPLATE)malloc(size);
79   if (dlg == NULL) {
80     return NULL;
81   }
82 
83   dlg->x  = x;
84   dlg->y  = y;
85   dlg->cx = cx;
86   dlg->cy = cy;
87 
88   dlg->cdit = 0;
89 
90   dlg->style = style;
91   if (font == NULL) {
92     dlg->style &= ~ DS_SETFONT;
93   } else {
94     dlg->style |= DS_SETFONT;
95   }
96   dlg->dwExtendedStyle = exstyle;
97 
98   ptr= (LPWORD)&dlg[1];
99   if (menu == NULL) {
100     *ptr++ = 0;
101   } else if (HIWORD(menu) == 0) {
102     ptr = setResourceID(ptr, LOWORD(menu));
103   } else {
104     ptr = appendString(ptr, menu);
105   }
106 
107   if ( class == NULL ) {
108     *ptr++ = 0;
109   } else if ( HIWORD(class) == 0 ) {
110     ptr = setResourceID(ptr, LOWORD(class));
111   } else {
112     ptr = appendString(ptr, class);
113   }
114 
115   ptr = appendString(ptr, (caption == NULL ? L"" : caption));
116 
117   if ( font != NULL ) {
118     *ptr++ = height;
119     ptr = appendString(ptr, font);
120   }
121 
122   dtemp = (DIA_TEMPLATE*)malloc(sizeof(DIA_TEMPLATE));
123   if ( dtemp == NULL )
124     return NULL;
125 
126   dtemp->dtemplate     = dlg;
127   dtemp->next_dia_item = (LPDLGITEMTEMPLATE)ptr;
128   dtemp->bytes_left    = (unsigned int)(((char*)dlg + size) - (char*)ptr);
129   dtemp->bytes_alloced = size;
130 
131   return dtemp;
132 }
133 
134 static
135 DIA_TEMPLATE*
check_if_enough_mem(DIA_TEMPLATE * dia,LPCWSTR text,LPCWSTR classname)136 check_if_enough_mem(DIA_TEMPLATE* dia, LPCWSTR text, LPCWSTR classname)
137 {
138  unsigned int sz = 0;
139 
140  sz += sizeof(DLGITEMTEMPLATE);
141 
142  if ( HIWORD(classname) == 0 ) {
143     sz += sizeof(WORD);
144  } else {
145     sz += wcslen(classname) + 1;
146  }
147  if ( HIWORD(text) == 0 ) {
148     sz += sizeof(WORD);
149  } else {
150     sz += wcslen(text) + 1;
151  }
152 
153  if ( sz >= dia->bytes_left ) {
154    unsigned int diff;
155    dia->bytes_left = dia->bytes_left + dia->bytes_alloced;
156    dia->bytes_alloced *= 2;
157    /* Being defensive here.. */
158    diff = (unsigned int)((char*)dia->next_dia_item - (char*)dia->dtemplate);
159    dia->dtemplate = (LPDLGTEMPLATE)realloc((void*)dia->dtemplate, dia->bytes_alloced);
160    if ( dia->dtemplate == NULL )
161      return NULL;
162    dia->next_dia_item  = (LPDLGITEMTEMPLATE)((char*)dia->dtemplate + diff);
163    return dia;
164   } else {
165    return dia;
166   }
167 }
168 
169 static
noParms(LPDLGITEMTEMPLATE item,LPWORD ptr)170 LPWORD noParms (LPDLGITEMTEMPLATE item, LPWORD ptr)
171 {
172   *ptr++ = 0;
173   if ( (((LPWORD)item) - ptr) & 0x1)
174      *ptr++ = 0;
175 
176   return ptr;
177 }
178 
179 DIA_TEMPLATE*
addDiaControl(DIA_TEMPLATE * dia,LPCWSTR text,short id,LPCWSTR classname,DWORD style,int x,int y,int cx,int cy,DWORD exstyle)180 addDiaControl
181          ( DIA_TEMPLATE* dia
182 	 , LPCWSTR text, short id
183 	 , LPCWSTR classname, DWORD style
184 	 , int x, int y, int cx, int cy
185 	 , DWORD exstyle
186 	 )
187 {
188   LPWORD ptr;
189   LPDLGITEMTEMPLATE item;
190 
191   dia = check_if_enough_mem(dia, text, classname);
192 
193   ptr = (LPWORD)&(dia->next_dia_item[1]);
194 
195   item = dia->next_dia_item;
196 
197   item->style = WS_CHILD | style;
198   item->dwExtendedStyle = exstyle;
199   item->x  = x;
200   item->y  = y;
201   item->cx = cx;
202   item->cy = cy;
203   item->id = (WORD)id;
204 
205   if ( HIWORD(classname) != 0 ) {
206      ptr = setClassName(item, classname);
207   } else {
208      ptr = setResourceID(ptr, LOWORD(classname));
209   }
210 
211   if ( HIWORD(text) != 0 ) {
212     ptr = appendString(ptr, text);
213   } else {
214     ptr = setResourceID(ptr, (short)(LOWORD(text)));
215   }
216 
217   ptr = noParms(item, ptr);
218 
219   dia->bytes_left    -= ((char*)ptr - ((char*)dia->next_dia_item));
220   dia->next_dia_item  = (LPDLGITEMTEMPLATE)ptr;
221 
222   return dia;
223 }
224 
225