cmd: DIR command outputs free space for the path.
[wine.git] / dlls / sane.ds / ui.c
blob557cf81e0b17365b69e770ddddcf4d998ca3fa3e
1 /*
2 * TWAIN32 Options UI
4 * Copyright 2006 CodeWeavers, Aric Stewart
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdio.h>
25 #include "sane_i.h"
26 #include "winuser.h"
27 #include "winnls.h"
28 #include "wingdi.h"
29 #include "prsht.h"
30 #include "wine/debug.h"
31 #include "resource.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(twain);
35 #define ID_BASE 0x100
36 #define ID_EDIT_BASE 0x1000
37 #define ID_STATIC_BASE 0x2000
39 static INT_PTR CALLBACK DialogProc (HWND , UINT , WPARAM , LPARAM );
40 static INT CALLBACK PropSheetProc(HWND, UINT,LPARAM);
42 static int create_leading_static(HDC hdc, const WCHAR *text,
43 LPDLGITEMTEMPLATEW* template_out, int y, int id)
45 LPDLGITEMTEMPLATEW tpl = NULL;
46 INT len;
47 SIZE size;
48 WORD *ptr;
49 LONG base;
51 *template_out = NULL;
53 if (!text)
54 return 0;
56 base = GetDialogBaseUnits();
58 len = lstrlenW(text) * sizeof(WCHAR);
59 len += sizeof(DLGITEMTEMPLATE);
60 len += 4*sizeof(WORD);
62 tpl = malloc(len);
63 tpl->style=WS_VISIBLE;
64 tpl->dwExtendedStyle = 0;
65 tpl->x = 4;
66 tpl->y = y;
67 tpl->id = ID_BASE;
69 GetTextExtentPoint32W(hdc,text,lstrlenW(text),&size);
71 tpl->cx = MulDiv(size.cx,4,LOWORD(base));
72 tpl->cy = MulDiv(size.cy,8,HIWORD(base)) * 2;
73 ptr = (WORD *)(tpl + 1);
74 *ptr++ = 0xffff;
75 *ptr++ = 0x0082;
76 lstrcpyW( ptr, text );
77 ptr += lstrlenW(ptr) + 1;
78 *ptr = 0;
80 *template_out = tpl;
81 return len;
84 static int create_trailing_edit(HDC hdc, LPDLGITEMTEMPLATEW* template_out, int id,
85 int y, const WCHAR *text,BOOL is_int)
87 LPDLGITEMTEMPLATEW tpl = NULL;
88 INT len;
89 WORD *ptr;
90 SIZE size;
91 LONG base;
92 static const char int_base[] = "0000 xxx";
93 static const char float_base[] = "0000.0000 xxx";
95 base = GetDialogBaseUnits();
97 len = lstrlenW(text) * sizeof(WCHAR);
98 len += sizeof(DLGITEMTEMPLATE);
99 len += 4*sizeof(WORD);
101 tpl = malloc(len);
102 tpl->style=WS_VISIBLE|ES_READONLY|WS_BORDER;
103 tpl->dwExtendedStyle = 0;
104 tpl->x = 1;
105 tpl->y = y;
106 tpl->id = id;
108 if (is_int)
109 GetTextExtentPoint32A(hdc,int_base,lstrlenA(int_base),&size);
110 else
111 GetTextExtentPoint32A(hdc,float_base,lstrlenA(float_base),&size);
113 tpl->cx = MulDiv(size.cx*2,4,LOWORD(base));
114 tpl->cy = MulDiv(size.cy,8,HIWORD(base)) * 2;
116 ptr = (WORD *)(tpl + 1);
117 *ptr++ = 0xffff;
118 *ptr++ = 0x0081;
119 lstrcpyW( ptr, text );
120 ptr += lstrlenW(ptr) + 1;
121 *ptr = 0;
123 *template_out = tpl;
124 return len;
128 static int create_item(HDC hdc, const struct option_descriptor *opt,
129 INT id, LPDLGITEMTEMPLATEW *template_out, int y, int *cx, int* count)
131 LPDLGITEMTEMPLATEW tpl = NULL,rc = NULL;
132 WORD class = 0xffff;
133 DWORD styles = WS_VISIBLE;
134 WORD *ptr = NULL;
135 LPDLGITEMTEMPLATEW lead_static = NULL;
136 LPDLGITEMTEMPLATEW trail_edit = NULL;
137 DWORD leading_len = 0;
138 DWORD trail_len = 0;
139 DWORD local_len = 0;
140 const WCHAR *title = NULL;
141 WCHAR buffer[255];
142 int padding = 0;
143 int padding2 = 0;
144 int base_x = 0;
145 LONG base;
146 int ctl_cx = 0;
147 SIZE size;
149 GetTextExtentPoint32A(hdc,"X",1,&size);
150 base = GetDialogBaseUnits();
151 base_x = MulDiv(size.cx,4,LOWORD(base));
153 switch (opt->type)
155 case TYPE_BOOL:
156 class = 0x0080; /* Button */
157 styles |= BS_AUTOCHECKBOX;
158 title = opt->title;
159 break;
160 case TYPE_INT:
162 int i;
163 sane_option_get_value( id - ID_BASE, &i );
164 swprintf(buffer, ARRAY_SIZE(buffer), L"%i", i);
166 switch (opt->constraint_type)
168 case CONSTRAINT_NONE:
169 class = 0x0081; /* Edit*/
170 styles |= ES_NUMBER;
171 title = buffer;
172 break;
173 case CONSTRAINT_RANGE:
174 class = 0x0084; /* scroll */
175 ctl_cx = 10 * base_x;
176 trail_len += create_trailing_edit(hdc, &trail_edit, id +
177 ID_EDIT_BASE, y,buffer,TRUE);
178 break;
179 default:
180 class= 0x0085; /* Combo */
181 ctl_cx = 10 * base_x;
182 styles |= CBS_DROPDOWNLIST;
183 break;
185 leading_len += create_leading_static(hdc, opt->title, &lead_static, y, id+ID_STATIC_BASE);
186 break;
188 case TYPE_FIXED:
190 int *i = calloc( opt->size, sizeof(int) );
192 sane_option_get_value( id - ID_BASE, i );
194 swprintf(buffer, ARRAY_SIZE(buffer), L"%f", *i / 65536.0);
195 free( i );
197 switch (opt->constraint_type)
199 case CONSTRAINT_NONE:
200 class = 0x0081; /* Edit */
201 title = buffer;
202 break;
203 case CONSTRAINT_RANGE:
204 class= 0x0084; /* scroll */
205 ctl_cx = 10 * base_x;
206 trail_len += create_trailing_edit(hdc, &trail_edit, id + ID_EDIT_BASE, y,buffer,FALSE);
207 break;
208 default:
209 class= 0x0085; /* Combo */
210 ctl_cx = 10 * base_x;
211 styles |= CBS_DROPDOWNLIST;
212 break;
214 leading_len += create_leading_static(hdc, opt->title, &lead_static, y, id+ID_STATIC_BASE);
215 break;
217 case TYPE_STRING:
219 char str[256];
220 switch (opt->constraint_type)
222 case CONSTRAINT_NONE:
223 class = 0x0081; /* Edit*/
224 break;
225 default:
226 class= 0x0085; /* Combo */
227 ctl_cx = opt->size * base_x;
228 styles |= CBS_DROPDOWNLIST;
229 break;
231 leading_len += create_leading_static(hdc, opt->title, &lead_static, y, id+ID_STATIC_BASE);
232 sane_option_get_value( id - ID_BASE, str );
233 MultiByteToWideChar( CP_UNIXCP, 0, str, -1, buffer, ARRAY_SIZE(buffer) );
234 title = buffer;
235 break;
237 case TYPE_BUTTON:
238 class = 0x0080; /* Button */
239 title = opt->title;
240 break;
241 case TYPE_GROUP:
242 class = 0x0080; /* Button */
243 styles |= BS_GROUPBOX;
244 title = opt->title;
245 break;
248 local_len += sizeof(DLGITEMTEMPLATE);
249 if (title) local_len += lstrlenW(title) * sizeof(WCHAR);
250 local_len += 4*sizeof(WORD);
252 padding = leading_len % sizeof(DWORD);
253 rc = realloc(lead_static, leading_len + local_len + padding);
254 tpl = (LPDLGITEMTEMPLATEW)((LPBYTE)rc + leading_len + padding);
255 tpl->style=styles;
256 tpl->dwExtendedStyle = 0;
257 if (lead_static)
258 tpl->x = rc->x + rc->cx + 1;
259 else if (opt->type == TYPE_GROUP)
260 tpl->x = 2;
261 else
262 tpl->x = 4;
263 tpl->y = y;
264 tpl->id = id;
266 if (title)
268 GetTextExtentPoint32W(hdc,title,lstrlenW(title),&size);
269 tpl->cx = size.cx;
270 tpl->cy = size.cy;
272 else
274 if (lead_static)
275 tpl->cy = rc->cy;
276 else
277 tpl->cy = 15;
279 if (!ctl_cx)
280 ctl_cx = 15;
282 tpl->cx = ctl_cx;
284 ptr = (WORD *)(tpl + 1);
285 *ptr++ = 0xffff;
286 *ptr++ = class;
287 if (title)
289 lstrcpyW( ptr, title );
290 ptr += lstrlenW(ptr);
292 *ptr++ = 0;
293 *ptr = 0;
295 if (trail_edit)
297 trail_edit->x = tpl->cx + tpl->x + 2;
298 *cx = trail_edit->x + trail_edit->cx;
300 padding2 = (leading_len + local_len + padding)% sizeof(DWORD);
302 rc = realloc( rc, leading_len + local_len + padding +padding2 + trail_len);
304 memcpy(((LPBYTE)rc) + leading_len + local_len + padding + padding2,
305 trail_edit,trail_len);
307 else
308 *cx = tpl->cx + tpl->x;
310 *template_out = rc;
311 if (leading_len)
312 *count = 2;
313 else
314 *count = 1;
316 if (trail_edit)
317 *count+=1;
319 free(trail_edit);
320 return leading_len + local_len + padding + padding2 + trail_len;
324 static LPDLGTEMPLATEW create_options_page(HDC hdc, int *from_index,
325 int optcount, BOOL split_tabs)
327 int i;
328 INT y = 2;
329 LPDLGTEMPLATEW tpl = NULL;
330 LPBYTE all_controls = NULL;
331 DWORD control_len = 0;
332 int max_cx = 0;
333 int group_max_cx = 0;
334 LPBYTE ptr;
335 int group_offset = -1;
336 INT control_count = 0;
338 for (i = *from_index; i < optcount; i++)
340 LPDLGITEMTEMPLATEW item_tpl = NULL;
341 struct option_descriptor opt;
342 int len;
343 int padding = 0;
344 int x;
345 int count;
346 int hold_for_group = 0;
348 opt.optno = i;
349 if (SANE_CALL( option_get_descriptor, &opt )) continue;
350 if (opt.type == TYPE_GROUP && split_tabs)
352 if (control_len > 0)
354 *from_index = i - 1;
355 goto exit;
357 else
359 *from_index = i;
360 return NULL;
363 if (!opt.is_active)
364 continue;
366 len = create_item(hdc, &opt, ID_BASE + i, &item_tpl, y, &x, &count);
368 control_count += count;
370 if (!len)
372 continue;
375 hold_for_group = y;
376 y+= item_tpl->cy + 1;
377 max_cx = max(max_cx, x + 2);
378 group_max_cx = max(group_max_cx, x );
380 padding = len % sizeof(DWORD);
382 if (all_controls)
384 all_controls = realloc(all_controls, control_len + len + padding);
385 memcpy(all_controls+control_len,item_tpl,len);
386 memset(all_controls+control_len+len,0xca,padding);
387 free(item_tpl);
389 else
391 if (!padding)
393 all_controls = (LPBYTE)item_tpl;
395 else
397 all_controls = malloc(len + padding);
398 memcpy(all_controls,item_tpl,len);
399 memset(all_controls+len,0xcb,padding);
400 free(item_tpl);
404 if (opt.type == TYPE_GROUP)
406 if (group_offset == -1)
408 group_offset = control_len;
409 group_max_cx = 0;
411 else
413 LPDLGITEMTEMPLATEW group =
414 (LPDLGITEMTEMPLATEW)(all_controls+group_offset);
416 group->cy = hold_for_group - group->y;
417 group->cx = group_max_cx;
419 group = (LPDLGITEMTEMPLATEW)(all_controls+control_len);
420 group->y += 2;
421 y+=2;
422 group_max_cx = 0;
423 group_offset = control_len;
427 control_len += len + padding;
430 if ( group_offset && !split_tabs )
432 LPDLGITEMTEMPLATEW group =
433 (LPDLGITEMTEMPLATEW)(all_controls+group_offset);
434 group->cy = y - group->y;
435 group->cx = group_max_cx;
436 y+=2;
439 *from_index = i-1;
440 exit:
442 tpl = malloc(sizeof(DLGTEMPLATE) + 3*sizeof(WORD) + control_len);
444 tpl->style = WS_VISIBLE | WS_OVERLAPPEDWINDOW;
445 tpl->dwExtendedStyle = 0;
446 tpl->cdit = control_count;
447 tpl->x = 0;
448 tpl->y = 0;
449 tpl->cx = max_cx + 10;
450 tpl->cy = y + 10;
451 ptr = (LPBYTE)tpl + sizeof(DLGTEMPLATE);
452 *(LPWORD)ptr = 0x0000;
453 ptr+=sizeof(WORD);
454 *(LPWORD)ptr = 0x0000;
455 ptr+=sizeof(WORD);
456 *(LPWORD)ptr = 0x0000;
457 ptr+=sizeof(WORD);
458 memcpy(ptr,all_controls,control_len);
460 free(all_controls);
462 return tpl;
465 BOOL DoScannerUI(void)
467 HDC hdc;
468 PROPSHEETPAGEW psp[10];
469 int page_count= 0;
470 PROPSHEETHEADERW psh;
471 int index = 1;
472 TW_UINT16 rc;
473 int optcount;
474 UINT psrc;
475 LPWSTR szCaption;
476 DWORD len;
478 hdc = GetDC(0);
480 memset(psp,0,sizeof(psp));
481 rc = sane_option_get_value( 0, &optcount );
482 if (rc != TWCC_SUCCESS)
484 ERR("Unable to read number of options\n");
485 return FALSE;
488 while (index < optcount)
490 struct option_descriptor opt;
492 psp[page_count].pResource = create_options_page(hdc, &index,
493 optcount, TRUE);
494 opt.optno = index;
495 SANE_CALL( option_get_descriptor, &opt );
497 if (opt.type == TYPE_GROUP)
499 psp[page_count].pszTitle = wcsdup( opt.title );
502 if (psp[page_count].pResource)
504 psp[page_count].dwSize = sizeof(PROPSHEETPAGEW);
505 psp[page_count].dwFlags = PSP_DLGINDIRECT | PSP_USETITLE;
506 psp[page_count].hInstance = SANE_instance;
507 psp[page_count].pfnDlgProc = DialogProc;
508 psp[page_count].lParam = (LPARAM)&activeDS;
509 page_count ++;
512 index ++;
515 len = lstrlenA(activeDS.identity.Manufacturer)
516 + lstrlenA(activeDS.identity.ProductName) + 2;
517 szCaption = malloc(len *sizeof(WCHAR));
518 MultiByteToWideChar(CP_ACP,0,activeDS.identity.Manufacturer,-1,
519 szCaption,len);
520 szCaption[lstrlenA(activeDS.identity.Manufacturer)] = ' ';
521 MultiByteToWideChar(CP_ACP,0,activeDS.identity.ProductName,-1,
522 &szCaption[lstrlenA(activeDS.identity.Manufacturer)+1],len);
523 psh.dwSize = sizeof(PROPSHEETHEADERW);
524 psh.dwFlags = PSH_PROPSHEETPAGE|PSH_PROPTITLE|PSH_USECALLBACK;
525 psh.hwndParent = activeDS.hwndOwner;
526 psh.hInstance = SANE_instance;
527 psh.pszIcon = 0;
528 psh.pszCaption = szCaption;
529 psh.nPages = page_count;
530 psh.nStartPage = 0;
531 psh.ppsp = (LPCPROPSHEETPAGEW)psp;
532 psh.pfnCallback = PropSheetProc;
534 psrc = PropertySheetW(&psh);
536 for(index = 0; index < page_count; index ++)
538 free((LPBYTE)psp[index].pResource);
539 free((LPBYTE)psp[index].pszTitle);
541 free(szCaption);
543 if (psrc == IDOK)
544 return TRUE;
545 else
546 return FALSE;
549 static void UpdateRelevantEdit(HWND hwnd, const struct option_descriptor *opt, int position)
551 WCHAR buffer[244];
552 HWND edit_w;
553 int len;
555 switch (opt->type)
557 case TYPE_INT:
559 INT si;
561 if (opt->constraint.range.quant)
562 si = position * opt->constraint.range.quant;
563 else
564 si = position;
566 len = swprintf( buffer, ARRAY_SIZE(buffer), L"%i", si );
567 break;
569 case TYPE_FIXED:
571 double dd;
573 if (opt->constraint.range.quant)
574 dd = position * (opt->constraint.range.quant / 65536.0);
575 else
576 dd = position * 0.01;
578 len = swprintf( buffer, ARRAY_SIZE(buffer), L"%f", dd );
579 break;
581 default:
582 return;
585 buffer[len++] = ' ';
586 LoadStringW( SANE_instance, opt->unit, buffer + len, ARRAY_SIZE( buffer ) - len );
588 edit_w = GetDlgItem(hwnd,opt->optno + ID_BASE + ID_EDIT_BASE);
589 if (edit_w) SetWindowTextW(edit_w,buffer);
593 static BOOL UpdateSaneScrollOption(const struct option_descriptor *opt, DWORD position)
595 BOOL result = FALSE;
596 int si;
598 switch (opt->type)
600 case TYPE_INT:
602 if (opt->constraint.range.quant)
603 si = position * opt->constraint.range.quant;
604 else
605 si = position;
607 sane_option_set_value( opt->optno, &si, &result );
608 break;
610 case TYPE_FIXED:
611 if (opt->constraint.range.quant)
612 si = position * opt->constraint.range.quant;
613 else
614 si = MulDiv( position, 65536, 100 );
616 sane_option_set_value( opt->optno, &si, &result );
617 break;
618 default:
619 break;
622 return result;
625 static INT_PTR InitializeDialog(HWND hwnd)
627 TW_UINT16 rc;
628 int optcount;
629 HWND control;
630 int i;
632 rc = sane_option_get_value( 0, &optcount );
633 if (rc != TWCC_SUCCESS)
635 ERR("Unable to read number of options\n");
636 return FALSE;
639 for ( i = 1; i < optcount; i++)
641 struct option_descriptor opt;
643 control = GetDlgItem(hwnd,i+ID_BASE);
645 if (!control)
646 continue;
648 opt.optno = i;
649 SANE_CALL( option_get_descriptor, &opt );
651 TRACE("%i %s %i %i\n",i,debugstr_w(opt.title),opt.type,opt.constraint_type);
652 EnableWindow(control,opt.is_active);
654 SendMessageA(control,CB_RESETCONTENT,0,0);
655 /* initialize values */
656 if (opt.type == TYPE_STRING && opt.constraint_type != CONSTRAINT_NONE)
658 CHAR buffer[255];
659 WCHAR *p;
661 for (p = opt.constraint.strings; *p; p += lstrlenW(p) + 1)
662 SendMessageW( control,CB_ADDSTRING,0, (LPARAM)p );
663 sane_option_get_value( i, buffer );
664 SendMessageA(control,CB_SELECTSTRING,0,(LPARAM)buffer);
666 else if (opt.type == TYPE_BOOL)
668 BOOL b;
669 sane_option_get_value( i, &b );
670 if (b)
671 SendMessageA(control,BM_SETCHECK,BST_CHECKED,0);
674 else if (opt.type == TYPE_INT && opt.constraint_type == CONSTRAINT_WORD_LIST)
676 int j, count = opt.constraint.word_list[0];
677 CHAR buffer[16];
678 int val;
679 for (j=1; j<=count; j++)
681 sprintf(buffer, "%d", opt.constraint.word_list[j]);
682 SendMessageA(control, CB_ADDSTRING, 0, (LPARAM)buffer);
684 sane_option_get_value( i, &val );
685 sprintf(buffer, "%d", val);
686 SendMessageA(control,CB_SELECTSTRING,0,(LPARAM)buffer);
688 else if (opt.constraint_type == CONSTRAINT_RANGE)
690 if (opt.type == TYPE_INT)
692 int si;
693 int min,max;
695 min = opt.constraint.range.min /
696 (opt.constraint.range.quant ? opt.constraint.range.quant : 1);
698 max = opt.constraint.range.max /
699 (opt.constraint.range.quant ? opt.constraint.range.quant : 1);
701 SendMessageA(control,SBM_SETRANGE,min,max);
703 sane_option_get_value( i, &si );
704 if (opt.constraint.range.quant)
705 si = si / opt.constraint.range.quant;
707 SendMessageW(control,SBM_SETPOS, si, TRUE);
708 UpdateRelevantEdit(hwnd, &opt, si);
710 else if (opt.type == TYPE_FIXED)
712 int pos, min, max, *sf;
714 if (opt.constraint.range.quant)
716 min = opt.constraint.range.min / opt.constraint.range.quant;
717 max = opt.constraint.range.max / opt.constraint.range.quant;
719 else
721 min = MulDiv( opt.constraint.range.min, 100, 65536 );
722 max = MulDiv( opt.constraint.range.max, 100, 65536 );
725 SendMessageA(control,SBM_SETRANGE,min,max);
728 sf = calloc( opt.size, sizeof(int) );
729 sane_option_get_value( i, sf );
731 /* Note that conversion of float -> SANE_Fixed is lossy;
732 * and when you truncate it into an integer, you can get
733 * unfortunate results. This calculation attempts
734 * to mitigate that harm */
735 if (opt.constraint.range.quant)
736 pos = *sf / opt.constraint.range.quant;
737 else
738 pos = MulDiv( *sf, 100, 65536 );
740 free(sf);
741 SendMessageW(control, SBM_SETPOS, pos, TRUE);
742 UpdateRelevantEdit(hwnd, &opt, pos);
747 return TRUE;
750 static INT_PTR ProcessScroll(HWND hwnd, WPARAM wParam, LPARAM lParam)
752 struct option_descriptor opt;
753 WORD scroll;
754 DWORD position;
756 opt.optno = GetDlgCtrlID((HWND)lParam)- ID_BASE;
757 if (opt.optno < 0)
758 return FALSE;
760 if (SANE_CALL( option_get_descriptor, &opt )) return FALSE;
762 scroll = LOWORD(wParam);
764 switch (scroll)
766 case SB_THUMBTRACK:
767 case SB_THUMBPOSITION:
769 SCROLLINFO si;
770 si.cbSize = sizeof(SCROLLINFO);
771 si.fMask = SIF_TRACKPOS;
772 GetScrollInfo((HWND)lParam,SB_CTL, &si);
773 position = si.nTrackPos;
775 break;
776 case SB_LEFT:
777 case SB_LINELEFT:
778 case SB_PAGELEFT:
779 position = SendMessageW((HWND)lParam,SBM_GETPOS,0,0);
780 position--;
781 break;
782 case SB_RIGHT:
783 case SB_LINERIGHT:
784 case SB_PAGERIGHT:
785 position = SendMessageW((HWND)lParam,SBM_GETPOS,0,0);
786 position++;
787 break;
788 default:
789 position = SendMessageW((HWND)lParam,SBM_GETPOS,0,0);
792 SendMessageW((HWND)lParam,SBM_SETPOS, position, TRUE);
793 position = SendMessageW((HWND)lParam,SBM_GETPOS,0,0);
795 UpdateRelevantEdit(hwnd, &opt, position);
796 if (UpdateSaneScrollOption(&opt, position))
797 InitializeDialog(hwnd);
799 return TRUE;
803 static void ButtonClicked(HWND hwnd, INT id, HWND control)
805 struct option_descriptor opt;
806 BOOL changed = FALSE;
808 opt.optno = id - ID_BASE;
809 if (opt.optno < 0)
810 return;
812 if (SANE_CALL( option_get_descriptor, &opt )) return;
814 if (opt.type == TYPE_BOOL)
816 BOOL r = SendMessageW(control,BM_GETCHECK,0,0)==BST_CHECKED;
817 sane_option_set_value( opt.optno, &r, &changed );
818 if (changed) InitializeDialog(hwnd);
822 static void ComboChanged(HWND hwnd, INT id, HWND control)
824 int selection;
825 int len;
826 struct option_descriptor opt;
827 char *value;
828 BOOL changed = FALSE;
830 opt.optno = id - ID_BASE;
831 if (opt.optno < 0)
832 return;
834 if (SANE_CALL( option_get_descriptor, &opt )) return;
836 selection = SendMessageW(control,CB_GETCURSEL,0,0);
837 len = SendMessageW(control,CB_GETLBTEXTLEN,selection,0);
839 len++;
840 value = malloc(len);
841 SendMessageA(control,CB_GETLBTEXT,selection,(LPARAM)value);
843 if (opt.type == TYPE_STRING)
845 sane_option_set_value( opt.optno, value, &changed );
847 else if (opt.type == TYPE_INT)
849 int val = atoi( value );
850 sane_option_set_value( opt.optno, &val, &changed );
852 if (changed) InitializeDialog(hwnd);
853 free( value );
857 static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
859 switch (msg)
861 case WM_INITDIALOG:
862 return InitializeDialog(hwndDlg);
863 case WM_HSCROLL:
864 return ProcessScroll(hwndDlg, wParam, lParam);
865 case WM_NOTIFY:
867 LPPSHNOTIFY psn = (LPPSHNOTIFY)lParam;
868 switch (((NMHDR*)lParam)->code)
870 case PSN_APPLY:
871 if (psn->lParam)
873 activeDS.currentState = 6;
874 SANE_Notify(MSG_XFERREADY);
876 break;
877 case PSN_QUERYCANCEL:
878 SANE_Notify(MSG_CLOSEDSREQ);
879 break;
880 case PSN_SETACTIVE:
881 InitializeDialog(hwndDlg);
882 break;
884 break;
886 case WM_COMMAND:
887 switch (HIWORD(wParam))
889 case BN_CLICKED:
890 ButtonClicked(hwndDlg,LOWORD(wParam), (HWND)lParam);
891 break;
892 case CBN_SELCHANGE:
893 ComboChanged(hwndDlg,LOWORD(wParam), (HWND)lParam);
897 return FALSE;
900 static int CALLBACK PropSheetProc(HWND hwnd, UINT msg, LPARAM lParam)
902 if (msg == PSCB_INITIALIZED)
904 /* rename OK button to Scan */
905 HWND scan = GetDlgItem(hwnd,IDOK);
906 SetWindowTextA(scan,"Scan");
908 return TRUE;
912 static INT_PTR CALLBACK ScanningProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
914 return FALSE;
917 HWND ScanningDialogBox(HWND dialog, LONG progress)
919 if (!dialog)
920 dialog = CreateDialogW(SANE_instance,
921 (LPWSTR)MAKEINTRESOURCE(IDD_DIALOG1), NULL, ScanningProc);
923 if (progress == -1)
925 EndDialog(dialog,0);
926 return NULL;
929 RedrawWindow(dialog,NULL,NULL,
930 RDW_INTERNALPAINT|RDW_UPDATENOW|RDW_ALLCHILDREN);
932 return dialog;