1 /* browse.c: tape browser dialog box
2 Copyright (c) 2002-2008 Philip Kendall, Marek Januszewski
3 Copyright (c) 2015 Sergio Baldoví
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
19 Author contact information:
20
21 E-mail: philip-fuse@shadowmagic.org.uk
22
23 */
24
25 #include <config.h>
26
27 #include <libspectrum.h>
28 #include <tchar.h>
29 #include <windows.h>
30
31 #include "fuse.h"
32 #include "tape.h"
33 #include "ui/ui.h"
34 #include "win32internals.h"
35
36 #include "browse.h"
37
38 static INT_PTR CALLBACK dialog_proc( HWND hwndDlg, UINT uMsg,
39 WPARAM wParam, LPARAM lParam );
40 static void add_block_details( libspectrum_tape_block *block, void *user_data );
41 static void select_row( LPNMITEMACTIVATE lpnmitem );
42
43 static HWND dialog; /* The dialog box itself */
44
45 static int dialog_created; /* Have we created the dialog box yet? */
46
47 void
menu_media_tape_browse(int action)48 menu_media_tape_browse( int action )
49 {
50 /* Firstly, stop emulation */
51 fuse_emulation_pause();
52
53 if( !dialog_created ) {
54 dialog = CreateDialog( fuse_hInstance, MAKEINTRESOURCE( IDD_BROWSE ),
55 fuse_hWnd, dialog_proc );
56 if( dialog == NULL ) { fuse_emulation_unpause(); return; }
57 }
58
59 if( ui_tape_browser_update( UI_TAPE_BROWSER_NEW_TAPE, NULL ) ) {
60 fuse_emulation_unpause();
61 return;
62 }
63
64 ShowWindow( dialog, SW_SHOW );
65
66 /* Carry on with emulation */
67 fuse_emulation_unpause();
68 }
69
70 static void
dialog_init(HWND hwndDlg)71 dialog_init( HWND hwndDlg )
72 {
73 size_t i;
74 LPCTSTR titles[3] = { _T( "" ), _T( "Block type" ), _T( "Data" ) };
75 int titles_widths[3] = { 16, 115, 150 };
76
77 /* set extended listview style to select full row, when an item is selected */
78 DWORD lv_ext_style;
79 lv_ext_style = SendDlgItemMessage( hwndDlg, IDC_BROWSE_LV,
80 LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0 );
81 lv_ext_style |= LVS_EX_FULLROWSELECT;
82 SendDlgItemMessage( hwndDlg, IDC_BROWSE_LV,
83 LVM_SETEXTENDEDLISTVIEWSTYLE, 0, lv_ext_style );
84
85 /* Create columns in the listview */
86 LVCOLUMN lvc;
87 lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT ;
88 lvc.fmt = LVCFMT_LEFT;
89
90 for( i = 0; i < 3; i++ ) {
91 if( i != 0 )
92 lvc.mask |= LVCF_SUBITEM;
93 lvc.cx = titles_widths[i];
94 lvc.pszText = (LPTSTR)titles[i];
95 SendDlgItemMessage( hwndDlg, IDC_BROWSE_LV, LVM_INSERTCOLUMN, i,
96 ( LPARAM ) &lvc );
97 }
98
99 /* create image list for the listview */
100 HBITMAP icon_tape_marker, icon_tape_marker_mask;
101 BITMAP bmp;
102 HIMAGELIST himl;
103
104 /* FIXME: need to destroy those objects later */
105 icon_tape_marker = LoadImage( fuse_hInstance, "win32bmp_tape_marker",
106 IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
107 icon_tape_marker_mask = LoadImage( fuse_hInstance, "win32bmp_tape_marker_mask",
108 IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
109 GetObject( icon_tape_marker, sizeof( bmp ), &bmp );
110
111 /* FIXME: destroy the list later */
112 himl = ImageList_Create( bmp.bmWidth, bmp.bmHeight,
113 ILC_COLOR | ILC_MASK, 1, 0 );
114
115 ImageList_Add( himl, icon_tape_marker, icon_tape_marker_mask );
116
117 SendDlgItemMessage( hwndDlg, IDC_BROWSE_LV, LVM_SETIMAGELIST,
118 LVSIL_SMALL, ( LPARAM ) himl );
119
120 dialog_created = 1;
121 }
122
123 static INT_PTR CALLBACK
dialog_proc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)124 dialog_proc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
125 {
126 /* FIXME: implement resizing the dialog */
127 switch( uMsg ) {
128
129 case WM_INITDIALOG:
130 dialog_init( hwndDlg );
131 return FALSE;
132
133 case WM_NOTIFY:
134 if( ( ( LPNMHDR ) lParam )->code == NM_DBLCLK ) {
135 if( ( ( LPNMHDR ) lParam )->idFrom == IDC_BROWSE_LV ) {
136 select_row( ( LPNMITEMACTIVATE ) lParam );
137 return 0;
138 }
139 }
140 break;
141
142 case WM_COMMAND:
143 if( LOWORD( wParam ) == IDCLOSE ) {
144 ShowWindow( dialog, SW_HIDE );
145 return 0;
146 }
147 break;
148
149 case WM_CLOSE:
150 /* Catch attempts to delete the window and just hide it instead */
151 ShowWindow( dialog, SW_HIDE );
152 return 0;
153 }
154 return FALSE;
155 }
156
157 int
ui_tape_browser_update(ui_tape_browser_update_type change GCC_UNUSED,libspectrum_tape_block * block GCC_UNUSED)158 ui_tape_browser_update( ui_tape_browser_update_type change GCC_UNUSED,
159 libspectrum_tape_block *block GCC_UNUSED )
160 {
161 int error, current_block;
162
163 if( !dialog_created ) return 0;
164
165 fuse_emulation_pause();
166
167 SendDlgItemMessage( dialog, IDC_BROWSE_LV, LVM_DELETEALLITEMS, 0, 0 );
168
169 error = tape_foreach( add_block_details, NULL );
170 if( error ) {
171 fuse_emulation_unpause();
172 return 1;
173 }
174
175 current_block = tape_get_current_block();
176 if( current_block != -1 ) {
177 LVITEM li;
178 li.mask = LVIF_IMAGE;
179 li.iItem = current_block;
180 li.iSubItem = 0;
181 li.iImage = 0;
182 SendDlgItemMessage( dialog, IDC_BROWSE_LV, LVM_SETITEM, 0, ( LPARAM ) &li );
183 }
184
185 if( tape_modified ) {
186 SendDlgItemMessage( dialog, IDC_BROWSE_MODIFIED, WM_SETTEXT,
187 0, ( LPARAM ) TEXT( "Tape modified" ) );
188 } else {
189 SendDlgItemMessage( dialog, IDC_BROWSE_MODIFIED, WM_SETTEXT,
190 0, ( LPARAM ) TEXT( "Tape not modified" ) );
191 }
192
193 fuse_emulation_unpause();
194
195 return 0;
196 }
197
198 static void
add_block_details(libspectrum_tape_block * block,void * user_data)199 add_block_details( libspectrum_tape_block *block, void *user_data )
200 {
201 TCHAR buffer[256];
202 TCHAR *details[3] = { &buffer[0], &buffer[80], &buffer[160] };
203 LV_ITEM lvi;
204 size_t i;
205
206 _tcscpy( details[0], "" );
207 libspectrum_tape_block_description( details[1], 80, block );
208 /* FIXME: why does it give such a big number of bytes? */
209 tape_block_details( details[2], 80, block );
210
211 lvi.mask = LVIF_TEXT | LVIF_IMAGE;
212 lvi.iImage = -1;
213 lvi.iItem = SendDlgItemMessage( dialog, IDC_BROWSE_LV,
214 LVM_GETITEMCOUNT, 0, 0 );
215 for( i = 0; i < 3; i++ ) {
216 lvi.iSubItem = i;
217 lvi.pszText = details[i];
218 if( i == 0 )
219 SendDlgItemMessage( dialog, IDC_BROWSE_LV, LVM_INSERTITEM, 0,
220 ( LPARAM ) &lvi );
221 else
222 SendDlgItemMessage( dialog, IDC_BROWSE_LV, LVM_SETITEM, 0,
223 ( LPARAM ) &lvi );
224 }
225 }
226
227 /* Called when a row is selected */
228 static void
select_row(LPNMITEMACTIVATE lpnmitem)229 select_row( LPNMITEMACTIVATE lpnmitem )
230 {
231 int current_block, row;
232
233 row = lpnmitem->iItem;
234
235 /* Don't do anything if the current block was clicked on */
236 current_block = tape_get_current_block();
237 if( row == current_block ) return;
238
239 /* Otherwise, select the new block */
240 tape_select_block_no_update( row );
241
242 /* set the marker at the current item, clear others */
243 size_t i, count;
244 count = SendDlgItemMessage( dialog, IDC_BROWSE_LV,
245 LVM_GETITEMCOUNT, 0, 0 );
246 LVITEM li;
247 li.mask = LVIF_IMAGE;
248 li.iSubItem = 0;
249
250 for( i=0; i<count; i++ ) {
251 li.iImage = ( i==row ? 0 : -1 );
252 li.iItem = i;
253 SendDlgItemMessage( dialog, IDC_BROWSE_LV, LVM_SETITEM, 0, ( LPARAM ) &li );
254 }
255 }
256