]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/qe4/mru.c
Merge branch 'NateEag-master-patch-12920' into 'master'
[xonotic/netradiant.git] / tools / quake2 / extra / qe4 / mru.c
1 /*
2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
4
5 This file is part of Quake 2 Tools source code.
6
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22
23 //*************************************************************
24 //  File name: mru.c
25 //
26 //  Description:
27 //
28 //      Routines for MRU support
29 //
30 //  Development Team:
31 //
32 //      Gilles Vollant (100144.2636@compuserve.com)
33 //
34 //*************************************************************
35
36 #include "globaldefs.h"
37 #include <windows.h>
38 #include <windowsx.h>
39 #include <string.h>
40
41 #include "mru.h"
42 // CreateMruMenu  : MRUMENU constructor
43 // wNbLruShowInit : nb of item showed in menu
44 // wNbLruMenuInit : nb of item stored in memory
45 // wMaxSizeLruItemInit : size max. of filename
46
47
48 //*************************************************************
49 //
50 //  CreateMruMenu()
51 //
52 //  Purpose:
53 //
54 //              Allocate and Initialize an MRU and return a pointer on it
55 //
56 //
57 //  Parameters:
58 //
59 //      WORD wNbLruShowInit -      Maximum number of item displayed on menu
60 //      WORD wNbLruMenuInit -      Maximum number of item stored in memory
61 //      WORD wMaxSizeLruItemInit - Maximum size of an item (ie size of pathname)
62 //      WORD wIdMruInit -          ID of the first item in the menu (default:IDMRU)
63 //
64 //
65 //  Return: (LPMRUMENU)
66 //
67 //      Pointer on a MRUMENU structure, used by other function
68 //
69 //
70 //  Comments:
71 //      wNbLruShowInit <= wNbLruMenuInit
72 //
73 //
74 //  History:    Date       Author       Comment
75 //              09/24/94   G. Vollant   Created
76 //
77 //*************************************************************
78
79 LPMRUMENU CreateMruMenu (WORD wNbLruShowInit,
80             WORD wNbLruMenuInit,WORD wMaxSizeLruItemInit,WORD wIdMruInit)
81 {
82 LPMRUMENU lpMruMenu;
83   lpMruMenu = (LPMRUMENU)GlobalAllocPtr(GHND,sizeof(MRUMENU));
84
85   lpMruMenu->wNbItemFill = 0;
86   lpMruMenu->wNbLruMenu = wNbLruMenuInit;
87   lpMruMenu->wNbLruShow = wNbLruShowInit;
88   lpMruMenu->wIdMru = wIdMruInit;
89   lpMruMenu->wMaxSizeLruItem = wMaxSizeLruItemInit;
90   lpMruMenu->lpMRU = (LPSTR)GlobalAllocPtr(GHND,
91                       lpMruMenu->wNbLruMenu*(UINT)lpMruMenu->wMaxSizeLruItem);
92   if (lpMruMenu->lpMRU == NULL)
93      {
94        GlobalFreePtr(lpMruMenu);
95        lpMruMenu =  NULL;
96      }
97   return lpMruMenu;
98 }
99
100 //*************************************************************
101 //
102 //  CreateMruMenuDefault()
103 //
104 //  Purpose:
105 //
106 //              Allocate and Initialize an MRU and return a pointer on it
107 //              Use default parameter
108 //
109 //
110 //  Parameters:
111 //
112 //
113 //  Return: (LPMRUMENU)
114 //
115 //      Pointer on a MRUMENU structure, used by other function
116 //
117 //
118 //  Comments:
119 //
120 //
121 //  History:    Date       Author       Comment
122 //              09/24/94   G. Vollant   Created
123 //
124 //*************************************************************
125
126 LPMRUMENU CreateMruMenuDefault()
127 {
128   return CreateMruMenu (NBMRUMENUSHOW,NBMRUMENU,MAXSIZEMRUITEM,IDMRU);
129 }
130
131
132 //*************************************************************
133 //
134 //  DeleteMruMenu()
135 //
136 //  Purpose:
137 //              Destructor :
138 //              Clean and free a MRUMENU structure
139 //
140 //  Parameters:
141 //
142 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU, allocated
143 //             by CreateMruMenu() or CreateMruMenuDefault()
144 //
145 //
146 //  Return: void
147 //
148 //
149 //  Comments:
150 //
151 //
152 //  History:    Date       Author       Comment
153 //              09/24/94   G. Vollant   Created
154 //
155 //*************************************************************
156 void DeleteMruMenu(LPMRUMENU lpMruMenu)
157 {
158   GlobalFreePtr(lpMruMenu->lpMRU);
159   GlobalFreePtr(lpMruMenu);
160 }
161
162 //*************************************************************
163 //
164 //  SetNbLruShow()
165 //
166 //  Purpose:
167 //              Change the maximum number of item displayed on menu
168 //
169 //  Parameters:
170 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU
171 //      WORD wNbLruShowInit -      Maximum number of item displayed on menu
172 //
173 //
174 //  Return: void
175 //
176 //
177 //  Comments:
178 //
179 //
180 //  History:    Date       Author       Comment
181 //              09/24/94   G. Vollant   Created
182 //
183 //*************************************************************
184 void SetNbLruShow   (LPMRUMENU lpMruMenu,WORD wNbLruShowInit)
185 {
186   lpMruMenu->wNbLruShow = min(wNbLruShowInit,lpMruMenu->wNbLruMenu);
187 }
188
189 //*************************************************************
190 //
191 //  SetMenuItem()
192 //
193 //  Purpose:
194 //              Set the filename of an item
195 //
196 //  Parameters:
197 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU
198 //      WORD wItem -               Number of Item to set, zero based
199 //      LPSTR lpItem -             String, contain the filename of the item
200 //
201 //
202 //  Return: (BOOL)
203 //      TRUE  - Function run successfully
204 //      FALSE - Function don't run successfully
205 //
206 //
207 //  Comments:
208 //      used when load .INI or reg database
209 //
210 //  History:    Date       Author       Comment
211 //              09/24/94   G. Vollant   Created
212 //
213 //*************************************************************
214 BOOL SetMenuItem    (LPMRUMENU lpMruMenu,WORD wItem,LPSTR lpItem)
215 {
216   if (wItem >= NBMRUMENU)
217     return FALSE;
218   _fstrncpy((lpMruMenu->lpMRU) +
219             ((lpMruMenu->wMaxSizeLruItem) * (UINT)wItem),
220             lpItem,lpMruMenu->wMaxSizeLruItem-1);
221   lpMruMenu->wNbItemFill = max(lpMruMenu->wNbItemFill,wItem+1);
222   return TRUE;
223 }
224
225 //*************************************************************
226 //
227 //  GetMenuItem()
228 //
229 //  Purpose:
230 //              Get the filename of an item
231 //
232 //  Parameters:
233 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU
234 //      WORD wItem -               Number of Item to set, zero based
235 //      BOOL fIDMBased -           TRUE :  wItem is based on ID menu item
236 //                                 FALSE : wItem is zero-based
237 //      LPSTR lpItem -             String where the filename of the item will be
238 //                                   stored by GetMenuItem()
239 //      UINT  uiSize -             Size of the lpItem buffer
240 //
241 //
242 //  Return: (BOOL)
243 //      TRUE  - Function run successfully
244 //      FALSE - Function don't run successfully
245 //
246 //
247 //  Comments:
248 //      Used for saving in .INI or reg database, or when user select
249 //        an MRU in File menu
250 //
251 //  History:    Date       Author       Comment
252 //              09/24/94   G. Vollant   Created
253 //
254 //*************************************************************
255 BOOL GetMenuItem    (LPMRUMENU lpMruMenu,WORD wItem,
256                      BOOL fIDMBased,LPSTR lpItem,UINT uiSize)
257 {
258   if (fIDMBased)
259     wItem -= (lpMruMenu->wIdMru + 1);
260   if (wItem >= lpMruMenu->wNbItemFill)
261     return FALSE;
262   _fstrncpy(lpItem,(lpMruMenu->lpMRU) +
263                 ((lpMruMenu->wMaxSizeLruItem) * (UINT)(wItem)),uiSize);
264   *(lpItem+uiSize-1) = '\0';
265   return TRUE;
266 }
267
268 //*************************************************************
269 //
270 //  AddNewItem()
271 //
272 //  Purpose:
273 //              Add an item at the begin of the list
274 //
275 //  Parameters:
276 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU
277 //      LPSTR lpItem -             String contain the filename to add
278 //
279 //  Return: (BOOL)
280 //      TRUE  - Function run successfully
281 //      FALSE - Function don't run successfully
282 //
283 //
284 //  Comments:
285 //      Used when used open a file (using File Open common
286 //        dialog, Drag and drop or MRU)
287 //
288 //  History:    Date       Author       Comment
289 //              09/24/94   G. Vollant   Created
290 //
291 //*************************************************************
292 void AddNewItem     (LPMRUMENU lpMruMenu,LPSTR lpItem)
293 {
294 WORD i,j;
295   for (i=0;i<lpMruMenu->wNbItemFill;i++)
296     if (lstrcmpi(lpItem,(lpMruMenu->lpMRU) +
297         ((lpMruMenu->wMaxSizeLruItem) * (UINT)i)) == 0)
298       {
299         // Shift the other items
300         for (j=i;j>0;j--)
301          lstrcpy((lpMruMenu->lpMRU) + (lpMruMenu->wMaxSizeLruItem * (UINT)j),
302                  (lpMruMenu->lpMRU) + (lpMruMenu->wMaxSizeLruItem * (UINT)(j-1)));
303         _fstrncpy(lpMruMenu->lpMRU,lpItem,lpMruMenu->wMaxSizeLruItem-1);
304         return ;
305       }
306   lpMruMenu->wNbItemFill = min(lpMruMenu->wNbItemFill+1,lpMruMenu->wNbLruMenu);
307   for (i=lpMruMenu->wNbItemFill-1;i>0;i--)
308      lstrcpy(lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)i),
309              lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)(i-1)));
310   _fstrncpy(lpMruMenu->lpMRU,lpItem,lpMruMenu->wMaxSizeLruItem-1);
311 }
312
313 //*************************************************************
314 //
315 //  DelMenuItem()
316 //
317 //  Purpose:
318 //              Delete an item
319 //
320 //  Parameters:
321 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU
322 //      WORD wItem -               Number of Item to set, zero based
323 //      BOOL fIDMBased -           TRUE :  wItem is based on ID menu item
324 //                                 FALSE : wItem is zero-based
325 //
326 //  Return: (BOOL)
327 //      TRUE  - Function run successfully
328 //      FALSE - Function don't run successfully
329 //
330 //
331 //  Comments:
332 //      Used when used open a file, using MRU, and when an error
333 //         occured (by example, when file was deleted)
334 //
335 //  History:    Date       Author       Comment
336 //              09/24/94   G. Vollant   Created
337 //
338 //*************************************************************
339 BOOL DelMenuItem(LPMRUMENU lpMruMenu,WORD wItem,BOOL fIDMBased)
340 {
341 WORD i;
342   if (fIDMBased)
343     wItem -= (lpMruMenu->wIdMru + 1);
344   if (lpMruMenu->wNbItemFill <= wItem)
345     return FALSE;
346   lpMruMenu->wNbItemFill--;
347   for (i=wItem;i<lpMruMenu->wNbItemFill;i++)
348      lstrcpy(lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)i),
349              lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)(i+1)));
350   return TRUE;
351 }
352
353 //*************************************************************
354 //
355 //  PlaceMenuMRUItem()
356 //
357 //  Purpose:
358 //              Add MRU at the end of a menu
359 //
360 //  Parameters:
361 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU
362 //      HMENU hMenu -              Handle of menu where MRU must be added
363 //      UINT uiItem -              Item of menu entry where MRU must be added
364 //
365 //  Return: void
366 //
367 //
368 //  Comments:
369 //      Used MRU is modified, for refresh the File menu
370 //
371 //  History:    Date       Author       Comment
372 //              09/24/94   G. Vollant   Created
373 //
374 //*************************************************************
375 void PlaceMenuMRUItem(LPMRUMENU lpMruMenu,HMENU hMenu,UINT uiItem)
376 {
377 int  i;
378 WORD wNbShow;
379   if (hMenu == NULL)
380     return;
381   // remove old MRU in menu
382   for (i=0;i<=(int)(lpMruMenu->wNbLruMenu);i++)
383     RemoveMenu(hMenu,i+lpMruMenu->wIdMru,MF_BYCOMMAND);
384
385   if (lpMruMenu->wNbItemFill == 0)
386     return;
387
388   // If they are item, insert a separator before the files
389   InsertMenu(hMenu,uiItem,MF_SEPARATOR,lpMruMenu->wIdMru,NULL);
390
391   wNbShow = min(lpMruMenu->wNbItemFill,lpMruMenu->wNbLruShow);
392   for (i=(int)wNbShow-1;i>=0;i--)
393   {
394   LPSTR lpTxt;
395     if (lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20))
396       {
397         wsprintf(lpTxt,"&%lu %s",
398                  (DWORD)(i+1),lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem*(UINT)i));
399         InsertMenu(hMenu,(((WORD)i)!=(wNbShow-1)) ? (lpMruMenu->wIdMru+i+2) : lpMruMenu->wIdMru,
400                    MF_STRING,lpMruMenu->wIdMru+i+1,lpTxt);
401         GlobalFreePtr(lpTxt);
402       }
403   }
404
405 }
406
407 ///////////////////////////////////////////
408
409
410
411 //*************************************************************
412 //
413 //  SaveMruInIni()
414 //
415 //  Purpose:
416 //              Save MRU in a private .INI
417 //
418 //  Parameters:
419 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU
420 //      LPSTR lpszSection  -       Points to a null-terminated string containing
421 //                                      the name of the section
422 //      LPSTR lpszFile -           Points to a null-terminated string that names
423 //                                      the initialization file.
424 //
425 //  Return: (BOOL)
426 //      TRUE  - Function run successfully
427 //      FALSE - Function don't run successfully
428 //
429 //
430 //  Comments:
431 //      See WritePrivateProfileString API for more info on lpszSection and lpszFile
432 //
433 //  History:    Date       Author       Comment
434 //              09/24/94   G. Vollant   Created
435 //
436 //*************************************************************
437 BOOL SaveMruInIni(LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile)
438 {
439 LPSTR lpTxt;
440 WORD i;
441
442   lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
443   if (lpTxt == NULL)
444     return FALSE;
445
446   for (i=0;i<lpMruMenu->wNbLruMenu;i++)
447     {
448     char szEntry[16];
449       wsprintf(szEntry,"File%lu",(DWORD)i+1);
450       if (!GetMenuItem(lpMruMenu,i,FALSE,lpTxt,lpMruMenu->wMaxSizeLruItem + 10))
451         *lpTxt = '\0';
452       WritePrivateProfileString(lpszSection,szEntry,lpTxt,lpszFile);
453     }
454   GlobalFreePtr(lpTxt);
455   WritePrivateProfileString(NULL,NULL,NULL,lpszFile); // flush cache
456   return TRUE;
457 }
458
459
460 //*************************************************************
461 //
462 //  LoadMruInIni()
463 //
464 //  Purpose:
465 //              Load MRU from a private .INI
466 //
467 //  Parameters:
468 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU
469 //      LPSTR lpszSection  -       Points to a null-terminated string containing
470 //                                      the name of the section
471 //      LPSTR lpszFile -           Points to a null-terminated string that names
472 //                                      the initialization file.
473 //
474 //  Return: (BOOL)
475 //      TRUE  - Function run successfully
476 //      FALSE - Function don't run successfully
477 //
478 //
479 //  Comments:
480 //      See GetPrivateProfileString API for more info on lpszSection and lpszFile
481 //
482 //  History:    Date       Author       Comment
483 //              09/24/94   G. Vollant   Created
484 //
485 //*************************************************************
486 BOOL LoadMruInIni(LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile)
487 {
488 LPSTR lpTxt;
489 WORD i;
490   lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
491   if (lpTxt == NULL)
492     return FALSE;
493
494   for (i=0;i<lpMruMenu->wNbLruMenu;i++)
495     {
496     char szEntry[16];
497
498       wsprintf(szEntry,"File%lu",(DWORD)i+1);
499       GetPrivateProfileString(lpszSection,szEntry,"",lpTxt,
500                               lpMruMenu->wMaxSizeLruItem + 10,lpszFile);
501       if (*lpTxt == '\0')
502         break;
503       SetMenuItem(lpMruMenu,i,lpTxt);
504     }
505   GlobalFreePtr(lpTxt);
506   return TRUE;
507 }
508
509 #if GDEF_OS_WINDOWS
510
511 BOOL IsWin395OrHigher(void)
512 {
513   WORD wVer;
514
515   wVer = LOWORD(GetVersion());
516   wVer = (((WORD)LOBYTE(wVer)) << 8) | (WORD)HIBYTE(wVer);
517
518   return (wVer >= 0x035F);              // 5F = 95 dec
519 }
520
521
522 //*************************************************************
523 //
524 //  SaveMruInReg()
525 //
526 //  Purpose:
527 //              Save MRU in the registry
528 //
529 //  Parameters:
530 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU
531 //      LPSTR lpszKey  -           Points to a null-terminated string
532 //                                      specifying  the name of a key that
533 //                                      this function opens or creates.
534 //
535 //  Return: (BOOL)
536 //      TRUE  - Function run successfully
537 //      FALSE - Function don't run successfully
538 //
539 //
540 //  Comments:
541 //      Win32 function designed for Windows NT and Windows 95
542 //      See RegCreateKeyEx API for more info on lpszKey
543 //
544 //  History:    Date       Author       Comment
545 //              09/24/94   G. Vollant   Created
546 //
547 //*************************************************************
548 BOOL SaveMruInReg(LPMRUMENU lpMruMenu,LPSTR lpszKey)
549 {
550 LPSTR lpTxt;
551 WORD i;
552 HKEY hCurKey;
553 DWORD dwDisp;
554
555   lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
556   if (lpTxt == NULL)
557     return FALSE;
558
559   RegCreateKeyEx(HKEY_CURRENT_USER,lpszKey,0,NULL,
560                   REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hCurKey,&dwDisp);
561
562   for (i=0;i<lpMruMenu->wNbLruMenu;i++)
563     {
564     char szEntry[16];
565       wsprintf(szEntry,"File%lu",(DWORD)i+1);
566       if (!GetMenuItem(lpMruMenu,i,FALSE,lpTxt,lpMruMenu->wMaxSizeLruItem + 10))
567         *lpTxt = '\0';
568       RegSetValueEx(hCurKey,szEntry,0,REG_SZ,lpTxt,lstrlen(lpTxt));
569     }
570   RegCloseKey(hCurKey);
571   GlobalFreePtr(lpTxt);
572   return TRUE;
573 }
574
575 //*************************************************************
576 //
577 //  LoadMruInReg()
578 //
579 //  Purpose:
580 //              Load MRU from the registry
581 //
582 //  Parameters:
583 //      LPMRUMENU lpMruMenu -      pointer on MRUMENU
584 //      LPSTR lpszKey  -           Points to a null-terminated string
585 //                                      specifying  the name of a key that
586 //                                      this function opens or creates.
587 //
588 //  Return: (BOOL)
589 //      TRUE  - Function run successfully
590 //      FALSE - Function don't run successfully
591 //
592 //
593 //  Comments:
594 //      Win32 function designed for Windows NT and Windows 95
595 //      See RegOpenKeyEx API for more info on lpszKey
596 //
597 //  History:    Date       Author       Comment
598 //              09/24/94   G. Vollant   Created
599 //
600 //*************************************************************
601 BOOL LoadMruInReg(LPMRUMENU lpMruMenu,LPSTR lpszKey)
602 {
603 LPSTR lpTxt;
604 WORD i;
605 HKEY hCurKey;
606 DWORD dwType;
607   lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
608   if (lpTxt == NULL)
609     return FALSE;
610
611   RegOpenKeyEx(HKEY_CURRENT_USER,lpszKey,0,KEY_READ,&hCurKey);
612
613
614   for (i=0;i<lpMruMenu->wNbLruMenu;i++)
615     {
616     char szEntry[16];
617     DWORD dwSizeBuf;
618       wsprintf(szEntry,"File%lu",(DWORD)i+1);
619       *lpTxt = '\0';
620       dwSizeBuf = lpMruMenu->wMaxSizeLruItem + 10;
621       RegQueryValueEx(hCurKey,szEntry,NULL,&dwType,(LPBYTE)lpTxt,&dwSizeBuf);
622       *(lpTxt+dwSizeBuf)='\0';
623       if (*lpTxt == '\0')
624         break;
625       SetMenuItem(lpMruMenu,i,lpTxt);
626     }
627   RegCloseKey(hCurKey);
628   GlobalFreePtr(lpTxt);
629   return TRUE;
630 }
631
632
633 //*************************************************************
634 //
635 //  GetWin32Kind()
636 //
637 //  Purpose:
638 //              Get the Win32 platform
639 //
640 //  Parameters:
641 //
642 //  Return: (WIN32KIND)
643 //      WINNT -           Run under Windows NT
644 //      WIN32S -          Run under Windows 3.1x + Win32s
645 //      WIN95ORGREATHER - Run under Windows 95
646 //
647 //
648 //  Comments:
649 //      Win32 function designed for Windows NT and Windows 95
650 //      See RegOpenKeyEx API for more info on lpszKey
651 //
652 //  History:    Date       Author       Comment
653 //              09/24/94   G. Vollant   Created
654 //
655 //*************************************************************
656 WIN32KIND GetWin32Kind()
657 {
658 BOOL IsWin395OrHigher(void);
659
660   WORD wVer;
661
662   if ((GetVersion() & 0x80000000) == 0)
663     return WINNT;
664   wVer = LOWORD(GetVersion());
665   wVer = (((WORD)LOBYTE(wVer)) << 8) | (WORD)HIBYTE(wVer);
666
667   if (wVer >= 0x035F)
668     return WIN95ORGREATHER;
669   else
670     return WIN32S;
671 }
672 #endif