diff --git a/rosapps/games/solitaire/cardlib/card.h b/rosapps/games/solitaire/cardlib/card.h index 13dc19055c2..dc85896e0ac 100644 --- a/rosapps/games/solitaire/cardlib/card.h +++ b/rosapps/games/solitaire/cardlib/card.h @@ -1,105 +1,105 @@ -// -// CardLib - Card class -// -// Freeware -// Copyright J Brown 2001 -// - -#ifndef _CARD_INCLUDED -#define _CARD_INCLUDED - -enum eSuit { Clubs = 0, Diamonds = 1, Hearts = 2, Spades = 3 }; -enum eValue { Ace = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7, - Eight = 8, Nine = 9, Ten = 10, Jack = 11, Queen = 12, King = 13 }; - -inline int MAKE_CARD(int Value, int Suit) -{ - if(Value < 1) Value = 1; - if(Value == 14) Value = 1; - if(Value > 13) Value = 13; - - if(Suit < 0) Suit = 0; - if(Suit > 3) Suit = 3; - - return ((Value - 1) * 4 + Suit); -} - -class Card -{ - friend class CardStack; - -public: - - Card() - { - nValue = 0; //ace of spades by default - fFaceUp = true; - } - - Card(int value, int suit) //specify a face value [1-13] and suit [0-3] - { - nValue = MAKE_CARD(value, suit); - fFaceUp = true; - } - - Card(int index) //specify a 0-51 index - { - if(index < 0) index = 0; - if(index > 51) index = 51; - - nValue = index; - fFaceUp = true; - } - - int Suit() const - { - return (nValue % 4); - } - - int LoVal() const - { - return (nValue / 4) + 1; - } - - int HiVal() const - { - return ((nValue < 4) ? 14 : (nValue / 4) + 1); - } - - int Idx() const //unique value (0-51 etc) - { - return nValue; - } - - bool FaceUp() const - { - return fFaceUp; - } - - bool FaceDown() const - { - return !fFaceUp; - } - - void SetFaceUp(bool fTrue) - { - fFaceUp = fTrue; - } - - bool IsBlack() const - { - return Suit() == 0 || Suit() == 3; - } - - bool IsRed() const - { - return !IsBlack(); - } - -private: - - int nValue; - bool fFaceUp; -}; - -#endif +// +// CardLib - Card class +// +// Freeware +// Copyright J Brown 2001 +// + +#ifndef _CARD_INCLUDED +#define _CARD_INCLUDED + +enum eSuit { Clubs = 0, Diamonds = 1, Hearts = 2, Spades = 3 }; +enum eValue { Ace = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7, + Eight = 8, Nine = 9, Ten = 10, Jack = 11, Queen = 12, King = 13 }; + +inline int MAKE_CARD(int Value, int Suit) +{ + if(Value < 1) Value = 1; + if(Value == 14) Value = 1; + if(Value > 13) Value = 13; + + if(Suit < 0) Suit = 0; + if(Suit > 3) Suit = 3; + + return ((Value - 1) * 4 + Suit); +} + +class Card +{ + friend class CardStack; + +public: + + Card() + { + nValue = 0; //ace of spades by default + fFaceUp = true; + } + + Card(int value, int suit) //specify a face value [1-13] and suit [0-3] + { + nValue = MAKE_CARD(value, suit); + fFaceUp = true; + } + + Card(int index) //specify a 0-51 index + { + if(index < 0) index = 0; + if(index > 51) index = 51; + + nValue = index; + fFaceUp = true; + } + + int Suit() const + { + return (nValue % 4); + } + + int LoVal() const + { + return (nValue / 4) + 1; + } + + int HiVal() const + { + return ((nValue < 4) ? 14 : (nValue / 4) + 1); + } + + int Idx() const //unique value (0-51 etc) + { + return nValue; + } + + bool FaceUp() const + { + return fFaceUp; + } + + bool FaceDown() const + { + return !fFaceUp; + } + + void SetFaceUp(bool fTrue) + { + fFaceUp = fTrue; + } + + bool IsBlack() const + { + return Suit() == 0 || Suit() == 3; + } + + bool IsRed() const + { + return !IsBlack(); + } + +private: + + int nValue; + bool fFaceUp; +}; + +#endif diff --git a/rosapps/games/solitaire/cardlib/cardbitmaps.cpp b/rosapps/games/solitaire/cardlib/cardbitmaps.cpp index 2611fa05c24..5b32ae4b550 100644 --- a/rosapps/games/solitaire/cardlib/cardbitmaps.cpp +++ b/rosapps/games/solitaire/cardlib/cardbitmaps.cpp @@ -1,281 +1,281 @@ -// -// CardLib - Card bitmap support -// -// Freeware -// Copyright J Brown 2001 -// -#include -#include "globals.h" -#include "cardcolor.h" - -#ifndef __REACTOS__ -#pragma comment( lib, "..\\CardLib\\cards16.lib" ) - -extern "C" HINSTANCE WINAPI LoadLibrary16( PSTR ); -extern "C" void WINAPI FreeLibrary16( HINSTANCE ); -#endif - -#define NUMCARDBITMAPS (52+16) - -void PaintRect(HDC hdc, RECT *rect, COLORREF col); - -void LoadCardBitmapsFromLibrary(HINSTANCE hCardDll, int *pwidth, int *pheight) -{ - HBITMAP hBitmap; - HDC hdcCard = NULL; - HANDLE hOld; - int i, xpos; - int width, height; - BITMAP bmp; - - for(i = 0; i < NUMCARDBITMAPS; i++) - { - //convert into the range used by the cdt_xxx functions - int val; - - if(i < 52) val = (i % 4) * 13 + (i/4); - else val = i; - - hBitmap = LoadBitmap(hCardDll, MAKEINTRESOURCE(val + 1)); - GetObject(hBitmap, sizeof(bmp), &bmp); - - width = bmp.bmWidth; - height = bmp.bmHeight; - - if(i == 0) //if first time through, create BIG bitmap.. - { - HDC hdc = GetDC(0); - __hdcCardBitmaps = CreateCompatibleDC(hdc); - __hbmCardBitmaps = CreateCompatibleBitmap(hdc, width * NUMCARDBITMAPS, height); - SelectObject(__hdcCardBitmaps, __hbmCardBitmaps); - - hdcCard = CreateCompatibleDC(0); - - ReleaseDC(0, hdc); - } - - hOld = SelectObject(hdcCard, hBitmap); - BitBlt(__hdcCardBitmaps, i*width, 0, width, height, hdcCard, 0, 0, SRCCOPY); - SelectObject(hdcCard, hOld); - - //Now draw a black border around each card... - xpos = i*width; - MoveToEx(__hdcCardBitmaps, xpos+2, 0, 0); - LineTo(__hdcCardBitmaps, xpos+width - 3, 0); - LineTo(__hdcCardBitmaps, xpos+width - 1, 2); - LineTo(__hdcCardBitmaps, xpos+width - 1, height - 3); //vertical - LineTo(__hdcCardBitmaps, xpos+width - 3, height - 1); - LineTo(__hdcCardBitmaps, xpos+2, height - 1); - LineTo(__hdcCardBitmaps, xpos+0, height - 3); - LineTo(__hdcCardBitmaps, xpos+0, 2); - LineTo(__hdcCardBitmaps, xpos+2, 0); - - DeleteObject(hBitmap); - } - - DeleteDC(hdcCard); - - *pwidth = width; - *pheight = height; - -} - -void LoadCardBitmaps(void) -{ - HINSTANCE hCardDll; - - - //If Windows NT/2000/XP - if(GetVersion() < 0x80000000) - { - hCardDll = LoadLibrary("cards.dll"); - - if(hCardDll == 0) - { - MessageBox(0, "Error loading cards.dll (32bit)", "Shed", MB_OK | MB_ICONEXCLAMATION); - PostQuitMessage(0); - return; - } - - LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight); - - FreeLibrary(hCardDll); - } -#ifndef __REACTOS__ - //Else, Win9X - else - { - hCardDll = LoadLibrary16("cards.dll"); - - if(hCardDll == 0) - { - MessageBox(0, "Error loading cards.dll (16bit)", "Shed", MB_OK | MB_ICONEXCLAMATION); - PostQuitMessage(0); - return; - } - - LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight); - - FreeLibrary16(hCardDll); - } -#endif -} - -void FreeCardBitmaps() -{ - DeleteObject (__hbmCardBitmaps); - DeleteDC (__hdcCardBitmaps); -} -// -// Paint a checkered rectangle, with each alternate -// pixel being assigned a different colour -// -static void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg) -{ - static WORD wCheckPat[8] = - { - 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555 - }; - - HBITMAP hbmp; - HBRUSH hbr, hbrold; - COLORREF fgold, bgold; - - hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat); - hbr = CreatePatternBrush(hbmp); - - //UnrealizeObject(hbr); - - SetBrushOrgEx(hdc, rect->left, rect->top, 0); - - hbrold = (HBRUSH)SelectObject(hdc, hbr); - - fgold = SetTextColor(hdc, fg); - bgold = SetBkColor(hdc, bg); - - PatBlt(hdc, rect->left, rect->top, - rect->right - rect->left, - rect->bottom - rect->top, - PATCOPY); - - SetBkColor(hdc, bgold); - SetTextColor(hdc, fgold); - - SelectObject(hdc, hbrold); - DeleteObject(hbr); - DeleteObject(hbmp); -} - -void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2) -{ - if(bg) *bg = crBase; - if(fg) *fg = ColorScaleRGB(crBase, RGB(255,255,255), 0.2);//RGB(49, 99, 140); - if(sh1) *sh1 = ColorScaleRGB(crBase, RGB(0,0,0), 0.4); - if(sh2) *sh2 = ColorScaleRGB(crBase, RGB(0,0,0), 0.2); -} - -HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height) -{ - HANDLE hold, hpold; - HBITMAP hbm = CreateCompatibleBitmap(hdcCompat, width, height); - - HPEN hpfg, hpbg, hpsh, hpsh2; - - RECT rect; - COLORREF fg, bg, shadow, shadow2; - - GetSinkCols(col, &fg, &bg, &shadow, &shadow2); - - hold = SelectObject(hdc, hbm); - - //fill with a solid base colour - SetRect(&rect, 0,0,width,height); - PaintRect(hdc, &rect, MAKE_PALETTERGB(bg)); - - //draw the outline - hpfg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(fg)); - hpbg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(bg)); - hpsh = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow)); - hpsh2= CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow2)); - - hpold = SelectObject(hdc, hpsh); - MoveToEx(hdc, 2, 0, NULL); - LineTo (hdc, width-3,0); - LineTo (hdc, width-1, 2); - - SelectObject(hdc, hpold); - hpold = SelectObject(hdc, hpsh2); - LineTo (hdc, width-1, height-3); //vertical - LineTo (hdc, width-3, height-1); - LineTo (hdc, 2, height-1); - LineTo (hdc, 0, height-3); - SelectObject(hdc, hpold); - hpold = SelectObject(hdc, hpsh); - - //MoveToEx( hdc, 0, height-3,0); - LineTo (hdc, 0, 2); - LineTo (hdc, 2, 0); - - SelectObject(hdc, hpold); - - //draw the highlight (vertical) - hpold = SelectObject(hdc, hpfg); - MoveToEx(hdc, width - 2, 3, NULL); - LineTo (hdc, width - 2, height - 2); - - //(horz) - MoveToEx(hdc, width - 3, height-2, NULL); - LineTo (hdc, 3, height-2); - SelectObject(hdc, hpold); - - //draw the background - InflateRect(&rect, -2, -2); - DrawCheckedRect(hdc, &rect, MAKE_PALETTERGB(bg), MAKE_PALETTERGB(fg)); - - //overwrite the top-left background pixel - SetPixel(hdc, 2, 2, MAKE_PALETTERGB(bg)); - - DeleteObject(hpsh); - DeleteObject(hpsh2); - DeleteObject(hpfg); - DeleteObject(hpbg); - - - return hbm; -} - - - -void CopyColor(PALETTEENTRY *pe, COLORREF col) -{ - pe->peBlue = GetBValue(col); - pe->peGreen = GetGValue(col); - pe->peRed = GetRValue(col); - pe->peFlags = 0; -} - -HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours) -{ - LOGPALETTE *lp; - HPALETTE hPalette; - - // Allocate memory for the logical palette - lp = (LOGPALETTE *)HeapAlloc( - GetProcessHeap(), 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * nNumColours); - - lp->palNumEntries = nNumColours; - lp->palVersion = 0x300; - - //copy the colours into the logical palette format - for(int i = 0; i < nNumColours; i++) - { - CopyColor(&lp->palPalEntry[i], cols[i]); - } - - // create palette! - hPalette = CreatePalette(lp); - - HeapFree(GetProcessHeap(), 0, lp); - - return hPalette; -} +// +// CardLib - Card bitmap support +// +// Freeware +// Copyright J Brown 2001 +// +#include +#include "globals.h" +#include "cardcolor.h" + +#ifndef __REACTOS__ +#pragma comment( lib, "..\\CardLib\\cards16.lib" ) + +extern "C" HINSTANCE WINAPI LoadLibrary16( PSTR ); +extern "C" void WINAPI FreeLibrary16( HINSTANCE ); +#endif + +#define NUMCARDBITMAPS (52+16) + +void PaintRect(HDC hdc, RECT *rect, COLORREF col); + +void LoadCardBitmapsFromLibrary(HINSTANCE hCardDll, int *pwidth, int *pheight) +{ + HBITMAP hBitmap; + HDC hdcCard = NULL; + HANDLE hOld; + int i, xpos; + int width, height; + BITMAP bmp; + + for(i = 0; i < NUMCARDBITMAPS; i++) + { + //convert into the range used by the cdt_xxx functions + int val; + + if(i < 52) val = (i % 4) * 13 + (i/4); + else val = i; + + hBitmap = LoadBitmap(hCardDll, MAKEINTRESOURCE(val + 1)); + GetObject(hBitmap, sizeof(bmp), &bmp); + + width = bmp.bmWidth; + height = bmp.bmHeight; + + if(i == 0) //if first time through, create BIG bitmap.. + { + HDC hdc = GetDC(0); + __hdcCardBitmaps = CreateCompatibleDC(hdc); + __hbmCardBitmaps = CreateCompatibleBitmap(hdc, width * NUMCARDBITMAPS, height); + SelectObject(__hdcCardBitmaps, __hbmCardBitmaps); + + hdcCard = CreateCompatibleDC(0); + + ReleaseDC(0, hdc); + } + + hOld = SelectObject(hdcCard, hBitmap); + BitBlt(__hdcCardBitmaps, i*width, 0, width, height, hdcCard, 0, 0, SRCCOPY); + SelectObject(hdcCard, hOld); + + //Now draw a black border around each card... + xpos = i*width; + MoveToEx(__hdcCardBitmaps, xpos+2, 0, 0); + LineTo(__hdcCardBitmaps, xpos+width - 3, 0); + LineTo(__hdcCardBitmaps, xpos+width - 1, 2); + LineTo(__hdcCardBitmaps, xpos+width - 1, height - 3); //vertical + LineTo(__hdcCardBitmaps, xpos+width - 3, height - 1); + LineTo(__hdcCardBitmaps, xpos+2, height - 1); + LineTo(__hdcCardBitmaps, xpos+0, height - 3); + LineTo(__hdcCardBitmaps, xpos+0, 2); + LineTo(__hdcCardBitmaps, xpos+2, 0); + + DeleteObject(hBitmap); + } + + DeleteDC(hdcCard); + + *pwidth = width; + *pheight = height; + +} + +void LoadCardBitmaps(void) +{ + HINSTANCE hCardDll; + + + //If Windows NT/2000/XP + if(GetVersion() < 0x80000000) + { + hCardDll = LoadLibrary("cards.dll"); + + if(hCardDll == 0) + { + MessageBox(0, "Error loading cards.dll (32bit)", "Shed", MB_OK | MB_ICONEXCLAMATION); + PostQuitMessage(0); + return; + } + + LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight); + + FreeLibrary(hCardDll); + } +#ifndef __REACTOS__ + //Else, Win9X + else + { + hCardDll = LoadLibrary16("cards.dll"); + + if(hCardDll == 0) + { + MessageBox(0, "Error loading cards.dll (16bit)", "Shed", MB_OK | MB_ICONEXCLAMATION); + PostQuitMessage(0); + return; + } + + LoadCardBitmapsFromLibrary(hCardDll, &__cardwidth, &__cardheight); + + FreeLibrary16(hCardDll); + } +#endif +} + +void FreeCardBitmaps() +{ + DeleteObject (__hbmCardBitmaps); + DeleteDC (__hdcCardBitmaps); +} +// +// Paint a checkered rectangle, with each alternate +// pixel being assigned a different colour +// +static void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg) +{ + static WORD wCheckPat[8] = + { + 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555 + }; + + HBITMAP hbmp; + HBRUSH hbr, hbrold; + COLORREF fgold, bgold; + + hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat); + hbr = CreatePatternBrush(hbmp); + + //UnrealizeObject(hbr); + + SetBrushOrgEx(hdc, rect->left, rect->top, 0); + + hbrold = (HBRUSH)SelectObject(hdc, hbr); + + fgold = SetTextColor(hdc, fg); + bgold = SetBkColor(hdc, bg); + + PatBlt(hdc, rect->left, rect->top, + rect->right - rect->left, + rect->bottom - rect->top, + PATCOPY); + + SetBkColor(hdc, bgold); + SetTextColor(hdc, fgold); + + SelectObject(hdc, hbrold); + DeleteObject(hbr); + DeleteObject(hbmp); +} + +void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2) +{ + if(bg) *bg = crBase; + if(fg) *fg = ColorScaleRGB(crBase, RGB(255,255,255), 0.2);//RGB(49, 99, 140); + if(sh1) *sh1 = ColorScaleRGB(crBase, RGB(0,0,0), 0.4); + if(sh2) *sh2 = ColorScaleRGB(crBase, RGB(0,0,0), 0.2); +} + +HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height) +{ + HANDLE hold, hpold; + HBITMAP hbm = CreateCompatibleBitmap(hdcCompat, width, height); + + HPEN hpfg, hpbg, hpsh, hpsh2; + + RECT rect; + COLORREF fg, bg, shadow, shadow2; + + GetSinkCols(col, &fg, &bg, &shadow, &shadow2); + + hold = SelectObject(hdc, hbm); + + //fill with a solid base colour + SetRect(&rect, 0,0,width,height); + PaintRect(hdc, &rect, MAKE_PALETTERGB(bg)); + + //draw the outline + hpfg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(fg)); + hpbg = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(bg)); + hpsh = CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow)); + hpsh2= CreatePen(PS_SOLID, 0, MAKE_PALETTERGB(shadow2)); + + hpold = SelectObject(hdc, hpsh); + MoveToEx(hdc, 2, 0, NULL); + LineTo (hdc, width-3,0); + LineTo (hdc, width-1, 2); + + SelectObject(hdc, hpold); + hpold = SelectObject(hdc, hpsh2); + LineTo (hdc, width-1, height-3); //vertical + LineTo (hdc, width-3, height-1); + LineTo (hdc, 2, height-1); + LineTo (hdc, 0, height-3); + SelectObject(hdc, hpold); + hpold = SelectObject(hdc, hpsh); + + //MoveToEx( hdc, 0, height-3,0); + LineTo (hdc, 0, 2); + LineTo (hdc, 2, 0); + + SelectObject(hdc, hpold); + + //draw the highlight (vertical) + hpold = SelectObject(hdc, hpfg); + MoveToEx(hdc, width - 2, 3, NULL); + LineTo (hdc, width - 2, height - 2); + + //(horz) + MoveToEx(hdc, width - 3, height-2, NULL); + LineTo (hdc, 3, height-2); + SelectObject(hdc, hpold); + + //draw the background + InflateRect(&rect, -2, -2); + DrawCheckedRect(hdc, &rect, MAKE_PALETTERGB(bg), MAKE_PALETTERGB(fg)); + + //overwrite the top-left background pixel + SetPixel(hdc, 2, 2, MAKE_PALETTERGB(bg)); + + DeleteObject(hpsh); + DeleteObject(hpsh2); + DeleteObject(hpfg); + DeleteObject(hpbg); + + + return hbm; +} + + + +void CopyColor(PALETTEENTRY *pe, COLORREF col) +{ + pe->peBlue = GetBValue(col); + pe->peGreen = GetGValue(col); + pe->peRed = GetRValue(col); + pe->peFlags = 0; +} + +HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours) +{ + LOGPALETTE *lp; + HPALETTE hPalette; + + // Allocate memory for the logical palette + lp = (LOGPALETTE *)HeapAlloc( + GetProcessHeap(), 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * nNumColours); + + lp->palNumEntries = nNumColours; + lp->palVersion = 0x300; + + //copy the colours into the logical palette format + for(int i = 0; i < nNumColours; i++) + { + CopyColor(&lp->palPalEntry[i], cols[i]); + } + + // create palette! + hPalette = CreatePalette(lp); + + HeapFree(GetProcessHeap(), 0, lp); + + return hPalette; +} diff --git a/rosapps/games/solitaire/cardlib/cardbutton.cpp b/rosapps/games/solitaire/cardlib/cardbutton.cpp index bfdfcf91218..a66c3f273c1 100644 --- a/rosapps/games/solitaire/cardlib/cardbutton.cpp +++ b/rosapps/games/solitaire/cardlib/cardbutton.cpp @@ -1,489 +1,489 @@ -// -// CardLib - CardButton class -// -// Freeware -// Copyright J Brown 2001 -// -#include -#include - -#include "cardlib.h" -#include "cardwindow.h" -#include "cardbutton.h" -#include "cardcolor.h" - -HPALETTE UseNicePalette(HDC, HPALETTE); -void RestorePalette(HDC, HPALETTE); - -void PaintRect(HDC hdc, RECT *rect, COLORREF colour); - -CardButton::CardButton(CardWindow &parent, int Id, TCHAR *szText, UINT Style, bool visible, - int x, int y, int width, int height) - - : parentWnd(parent), id(Id), uStyle(Style), fVisible(visible), ButtonCallback(0) -{ - crText = RGB(255,255,255); - crBack = RGB(0, 128, 0); - - xadjust = 0; - yadjust = 0; - xjustify = 0; - yjustify = 0; - - fMouseDown = false; - fButtonDown = false; - - hIcon = 0; - - SetText(szText); - Move(x, y, width, height); - - mxlock = CreateMutex(0, FALSE, 0); - - hFont = 0; -} - -CardButton::~CardButton() -{ - CloseHandle(mxlock); -} - -void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal) -{ - RECT fill; - - HANDLE hOld; - - HPEN hhi = CreatePen(0, 0, MAKE_PALETTERGB(crHighlight)); - HPEN hsh = CreatePen(0, 0, MAKE_PALETTERGB(crShadow)); - HPEN hbl = (HPEN)GetStockObject(BLACK_PEN); - - int x = rect->left; - int y = rect->top; - int width = rect->right-rect->left - 1; - int height = rect->bottom-rect->top - 1; - - SetRect(&fill, x+1, y+1, x+width-1, y+height-1); - - int one = 1; - - if(!fNormal) - { - x += width; - y += height; - width = -width; - height = -height; - one = -1; - OffsetRect(&fill, 1, 1); - } - - if(fNormal) - hOld = SelectObject(hdc, hhi); - else - hOld = SelectObject(hdc, hhi); - - MoveToEx(hdc, x, y+height, 0); - LineTo(hdc, x, y); - LineTo(hdc, x+width, y); - SelectObject(hdc, hOld); - - hOld = SelectObject(hdc, hbl); - LineTo(hdc, x+width, y+height); - LineTo(hdc, x-one, y+height); - SelectObject(hdc, hOld); - - hOld = SelectObject(hdc, hsh); - MoveToEx(hdc, x+one, y+height-one, 0); - LineTo(hdc, x+width-one, y+height-one); - LineTo(hdc, x+width-one, y); - SelectObject(hdc, hOld); - - PaintRect(hdc, &fill, MAKE_PALETTERGB(crBack)); - - DeleteObject(hhi); - DeleteObject(hsh); -} - -void CardButton::Clip(HDC hdc) -{ - if(fVisible == false) return; - - ExcludeClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom); -} - -void CardButton::Draw(HDC hdc, bool fNormal) -{ - SIZE textsize; - int x, y; //text x, y - int ix, iy; //icon x, y - int iconwidth = 0; - - RECT cliprect; - - if(fVisible == 0) return; - - if(hFont == 0) - SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); - else - SelectObject(hdc, hFont); - - GetTextExtentPoint32(hdc, szText, lstrlen(szText), &textsize); - - if(hIcon) - { - x = rect.left + 32 + 8; - } - else - { - if(uStyle & CB_ALIGN_LEFT) - { - x = rect.left + iconwidth; - } - else if(uStyle & CB_ALIGN_RIGHT) - { - x = rect.left + (rect.right-rect.left-iconwidth-textsize.cx); - } - else //centered - { - x = rect.right - rect.left - iconwidth; - x = (x - textsize.cx) / 2; - x += rect.left + iconwidth; - } - } - - y = rect.bottom - rect.top; - y = (y - textsize.cy) / 2; - y += rect.top; - - //calc icon position.. - ix = rect.left + 4; - iy = rect.top + (rect.bottom-rect.top-32) / 2; - - //if button is pressed, then shift text - if(fNormal == false && (uStyle & CB_PUSHBUTTON)) - { - x += 1; - y += 1; - ix += 1; - iy += 1; - } - - SetRect(&cliprect, x, y, x+textsize.cx, y+textsize.cy); - ExcludeClipRect(hdc, x, y, x+textsize.cx, y+textsize.cy); - - // - // Calc icon pos - // - - if(hIcon) - { - ExcludeClipRect(hdc, ix, iy, ix + 32, iy + 32); - } - - if(uStyle & CB_PUSHBUTTON) - { - DrawRect(hdc, &rect, fNormal); - - SetBkColor(hdc, MAKE_PALETTERGB(crBack)); - SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText)); - - SelectClipRgn(hdc, 0); - - ExtTextOut(hdc, x, y, ETO_OPAQUE, &cliprect, szText, lstrlen(szText), 0); - } - else - { - SetBkColor(hdc, MAKE_PALETTERGB(crBack)); - SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText)); - - SelectClipRgn(hdc, 0); - - ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0); - } - - if(hIcon) - { - HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBack)); - DrawIconEx(hdc, ix, iy, hIcon, 32, 32, 0, hbr, 0); - DeleteObject(hbr); - } - -} - -void CardButton::AdjustPosition(int winwidth, int winheight) -{ - int width = rect.right-rect.left; - int height = rect.bottom-rect.top; - - width = width & ~0x1; - - switch(xjustify) - { - case CS_XJUST_NONE: - break; - - case CS_XJUST_CENTER: //centered - rect.left = (winwidth - (width)) / 2; - rect.left += xadjust; - rect.right = rect.left+width; - break; - - case CS_XJUST_RIGHT: //right-aligned - rect.left = winwidth - width; - rect.left += xadjust; - rect.right = rect.left+width; - break; - } - - switch(yjustify) - { - case CS_YJUST_NONE: - break; - - case CS_YJUST_CENTER: //centered - rect.top = (winheight - (height)) / 2; - rect.top += yadjust; - rect.bottom = rect.top+height; - break; - - case CS_YJUST_BOTTOM: //right-aligned - rect.top = winheight - height; - rect.top += yadjust; - rect.bottom = rect.top+height; - break; - } - -} - -int CardButton::OnLButtonDown(HWND hwnd, int x, int y) -{ - if((uStyle & CB_PUSHBUTTON) == 0) - return 0; - - //make sure that the user is allowed to do something - if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0) - { - return 0; - } - else - { - ReleaseMutex(mxlock); - } - - fMouseDown = true; - fButtonDown = true; - - Redraw(); - - SetCapture(hwnd); - - return 1; -} - -int CardButton::OnMouseMove(HWND hwnd, int x, int y) -{ - if(fMouseDown) - { - bool fOldButtonDown = fButtonDown; - - POINT pt; - - pt.x = x; - pt.y = y; - - if(PtInRect(&rect, pt)) - fButtonDown = true; - else - fButtonDown = false; - - if(fButtonDown != fOldButtonDown) - Redraw(); - } - - return 0; -} - -int CardButton::OnLButtonUp(HWND hwnd, int x, int y) -{ - if(fMouseDown) - { - fMouseDown = false; - fButtonDown = false; - - if(uStyle & CB_PUSHBUTTON) - { - Redraw(); - ReleaseCapture(); - } - - //if have clicked the button - if(parentWnd.CardButtonFromPoint(x, y) == this) - { - if(ButtonCallback) - { - ButtonCallback(*this); - } - else - { - HWND hwnd = (HWND)parentWnd; - SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), (LONG)hwnd); - } - } - } - - return 0; -} - -#define _countof(array) (sizeof(array)/sizeof(array[0])) - -CardButton *CardWindow::CreateButton(int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height) -{ - CardButton *cb; - - if(nNumButtons == MAXBUTTONS) - return 0; - - cb = new CardButton(*this, id, szText, uStyle, fVisible, x, y, width, height); - Buttons[nNumButtons++] = cb; - - if(uStyle & CB_PUSHBUTTON) - { - cb->SetBackColor(CardButton::GetFace(crBackgnd)); - //cb->SetBackColor(ScaleLumRGB(crBackgnd, 0.1)); - cb->SetForeColor(RGB(255,255,255)); - } - else - { - cb->SetBackColor(crBackgnd); - cb->SetForeColor(RGB(255,255,255)); - } - - return cb; -} - -void CardButton::SetText(TCHAR *lpszFormat, ...) -{ - int count; - - va_list args; - va_start(args, lpszFormat); - - count = wvsprintf(szText, lpszFormat, args); - va_end(args); -} - -int CardButton::Id() -{ - return id; -} - -void CardButton::Show(bool fShow) -{ - fVisible = fShow; -} - -void CardButton::Move(int x, int y, int width, int height) -{ - SetRect(&rect, x, y, x+width, y+height); -} - -void CardButton::Redraw() -{ - HDC hdc = GetDC((HWND)parentWnd); - - HPALETTE hOldPal = UseNicePalette(hdc, __hPalette); - - Draw(hdc, !fButtonDown); - - RestorePalette(hdc, hOldPal); - - ReleaseDC((HWND)parentWnd, hdc); -} - -void CardButton::SetForeColor(COLORREF cr) -{ - crText = cr; -} - -void CardButton::SetBackColor(COLORREF cr) -{ - crBack = cr; - - crHighlight = GetHighlight(cr); - crShadow = GetShadow(cr); - - //crHighlight = ScaleLumRGB(cr, +0.25); - //crShadow = ScaleLumRGB(cr, -0.25); -} - -// Static member -COLORREF CardButton::GetHighlight(COLORREF crBase) -{ - return ColorScaleRGB(crBase, RGB(255,255,255), 0.25); -} - -// Static member -COLORREF CardButton::GetShadow(COLORREF crBase) -{ - return ColorScaleRGB(crBase, RGB(0, 0, 0), 0.25); -} - -COLORREF CardButton::GetFace(COLORREF crBase) -{ - return ColorScaleRGB(crBase, RGB(255,255,255), 0.1); -} - -void CardButton::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust) -{ - xadjust = xAdjust; - yadjust = yAdjust; - xjustify = xJustify; - yjustify = yJustify; -} - -void CardButton::SetIcon(HICON hicon, bool fRedraw) -{ - hIcon = hicon; - - if(fRedraw) - Redraw(); -} - -void CardButton::SetFont(HFONT font) -{ - //don't delete the existing font.. - hFont = font; -} - -void CardButton::SetButtonProc(pButtonProc proc) -{ - ButtonCallback = proc; -} - -bool CardButton::Lock() -{ - DWORD dw = WaitForSingleObject(mxlock, 0); - - if(dw == WAIT_OBJECT_0) - return true; - else - return false; -} - -bool CardButton::UnLock() -{ - if(ReleaseMutex(mxlock)) - return true; - else - return false; -} - -void CardButton::SetStyle(UINT style) -{ - uStyle = style; -} - -UINT CardButton::GetStyle() -{ - return uStyle; -} +// +// CardLib - CardButton class +// +// Freeware +// Copyright J Brown 2001 +// +#include +#include + +#include "cardlib.h" +#include "cardwindow.h" +#include "cardbutton.h" +#include "cardcolor.h" + +HPALETTE UseNicePalette(HDC, HPALETTE); +void RestorePalette(HDC, HPALETTE); + +void PaintRect(HDC hdc, RECT *rect, COLORREF colour); + +CardButton::CardButton(CardWindow &parent, int Id, TCHAR *szText, UINT Style, bool visible, + int x, int y, int width, int height) + + : parentWnd(parent), id(Id), uStyle(Style), fVisible(visible), ButtonCallback(0) +{ + crText = RGB(255,255,255); + crBack = RGB(0, 128, 0); + + xadjust = 0; + yadjust = 0; + xjustify = 0; + yjustify = 0; + + fMouseDown = false; + fButtonDown = false; + + hIcon = 0; + + SetText(szText); + Move(x, y, width, height); + + mxlock = CreateMutex(0, FALSE, 0); + + hFont = 0; +} + +CardButton::~CardButton() +{ + CloseHandle(mxlock); +} + +void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal) +{ + RECT fill; + + HANDLE hOld; + + HPEN hhi = CreatePen(0, 0, MAKE_PALETTERGB(crHighlight)); + HPEN hsh = CreatePen(0, 0, MAKE_PALETTERGB(crShadow)); + HPEN hbl = (HPEN)GetStockObject(BLACK_PEN); + + int x = rect->left; + int y = rect->top; + int width = rect->right-rect->left - 1; + int height = rect->bottom-rect->top - 1; + + SetRect(&fill, x+1, y+1, x+width-1, y+height-1); + + int one = 1; + + if(!fNormal) + { + x += width; + y += height; + width = -width; + height = -height; + one = -1; + OffsetRect(&fill, 1, 1); + } + + if(fNormal) + hOld = SelectObject(hdc, hhi); + else + hOld = SelectObject(hdc, hhi); + + MoveToEx(hdc, x, y+height, 0); + LineTo(hdc, x, y); + LineTo(hdc, x+width, y); + SelectObject(hdc, hOld); + + hOld = SelectObject(hdc, hbl); + LineTo(hdc, x+width, y+height); + LineTo(hdc, x-one, y+height); + SelectObject(hdc, hOld); + + hOld = SelectObject(hdc, hsh); + MoveToEx(hdc, x+one, y+height-one, 0); + LineTo(hdc, x+width-one, y+height-one); + LineTo(hdc, x+width-one, y); + SelectObject(hdc, hOld); + + PaintRect(hdc, &fill, MAKE_PALETTERGB(crBack)); + + DeleteObject(hhi); + DeleteObject(hsh); +} + +void CardButton::Clip(HDC hdc) +{ + if(fVisible == false) return; + + ExcludeClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom); +} + +void CardButton::Draw(HDC hdc, bool fNormal) +{ + SIZE textsize; + int x, y; //text x, y + int ix, iy; //icon x, y + int iconwidth = 0; + + RECT cliprect; + + if(fVisible == 0) return; + + if(hFont == 0) + SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); + else + SelectObject(hdc, hFont); + + GetTextExtentPoint32(hdc, szText, lstrlen(szText), &textsize); + + if(hIcon) + { + x = rect.left + 32 + 8; + } + else + { + if(uStyle & CB_ALIGN_LEFT) + { + x = rect.left + iconwidth; + } + else if(uStyle & CB_ALIGN_RIGHT) + { + x = rect.left + (rect.right-rect.left-iconwidth-textsize.cx); + } + else //centered + { + x = rect.right - rect.left - iconwidth; + x = (x - textsize.cx) / 2; + x += rect.left + iconwidth; + } + } + + y = rect.bottom - rect.top; + y = (y - textsize.cy) / 2; + y += rect.top; + + //calc icon position.. + ix = rect.left + 4; + iy = rect.top + (rect.bottom-rect.top-32) / 2; + + //if button is pressed, then shift text + if(fNormal == false && (uStyle & CB_PUSHBUTTON)) + { + x += 1; + y += 1; + ix += 1; + iy += 1; + } + + SetRect(&cliprect, x, y, x+textsize.cx, y+textsize.cy); + ExcludeClipRect(hdc, x, y, x+textsize.cx, y+textsize.cy); + + // + // Calc icon pos + // + + if(hIcon) + { + ExcludeClipRect(hdc, ix, iy, ix + 32, iy + 32); + } + + if(uStyle & CB_PUSHBUTTON) + { + DrawRect(hdc, &rect, fNormal); + + SetBkColor(hdc, MAKE_PALETTERGB(crBack)); + SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText)); + + SelectClipRgn(hdc, 0); + + ExtTextOut(hdc, x, y, ETO_OPAQUE, &cliprect, szText, lstrlen(szText), 0); + } + else + { + SetBkColor(hdc, MAKE_PALETTERGB(crBack)); + SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText)); + + SelectClipRgn(hdc, 0); + + ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0); + } + + if(hIcon) + { + HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBack)); + DrawIconEx(hdc, ix, iy, hIcon, 32, 32, 0, hbr, 0); + DeleteObject(hbr); + } + +} + +void CardButton::AdjustPosition(int winwidth, int winheight) +{ + int width = rect.right-rect.left; + int height = rect.bottom-rect.top; + + width = width & ~0x1; + + switch(xjustify) + { + case CS_XJUST_NONE: + break; + + case CS_XJUST_CENTER: //centered + rect.left = (winwidth - (width)) / 2; + rect.left += xadjust; + rect.right = rect.left+width; + break; + + case CS_XJUST_RIGHT: //right-aligned + rect.left = winwidth - width; + rect.left += xadjust; + rect.right = rect.left+width; + break; + } + + switch(yjustify) + { + case CS_YJUST_NONE: + break; + + case CS_YJUST_CENTER: //centered + rect.top = (winheight - (height)) / 2; + rect.top += yadjust; + rect.bottom = rect.top+height; + break; + + case CS_YJUST_BOTTOM: //right-aligned + rect.top = winheight - height; + rect.top += yadjust; + rect.bottom = rect.top+height; + break; + } + +} + +int CardButton::OnLButtonDown(HWND hwnd, int x, int y) +{ + if((uStyle & CB_PUSHBUTTON) == 0) + return 0; + + //make sure that the user is allowed to do something + if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0) + { + return 0; + } + else + { + ReleaseMutex(mxlock); + } + + fMouseDown = true; + fButtonDown = true; + + Redraw(); + + SetCapture(hwnd); + + return 1; +} + +int CardButton::OnMouseMove(HWND hwnd, int x, int y) +{ + if(fMouseDown) + { + bool fOldButtonDown = fButtonDown; + + POINT pt; + + pt.x = x; + pt.y = y; + + if(PtInRect(&rect, pt)) + fButtonDown = true; + else + fButtonDown = false; + + if(fButtonDown != fOldButtonDown) + Redraw(); + } + + return 0; +} + +int CardButton::OnLButtonUp(HWND hwnd, int x, int y) +{ + if(fMouseDown) + { + fMouseDown = false; + fButtonDown = false; + + if(uStyle & CB_PUSHBUTTON) + { + Redraw(); + ReleaseCapture(); + } + + //if have clicked the button + if(parentWnd.CardButtonFromPoint(x, y) == this) + { + if(ButtonCallback) + { + ButtonCallback(*this); + } + else + { + HWND hwnd = (HWND)parentWnd; + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), (LONG)hwnd); + } + } + } + + return 0; +} + +#define _countof(array) (sizeof(array)/sizeof(array[0])) + +CardButton *CardWindow::CreateButton(int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height) +{ + CardButton *cb; + + if(nNumButtons == MAXBUTTONS) + return 0; + + cb = new CardButton(*this, id, szText, uStyle, fVisible, x, y, width, height); + Buttons[nNumButtons++] = cb; + + if(uStyle & CB_PUSHBUTTON) + { + cb->SetBackColor(CardButton::GetFace(crBackgnd)); + //cb->SetBackColor(ScaleLumRGB(crBackgnd, 0.1)); + cb->SetForeColor(RGB(255,255,255)); + } + else + { + cb->SetBackColor(crBackgnd); + cb->SetForeColor(RGB(255,255,255)); + } + + return cb; +} + +void CardButton::SetText(TCHAR *lpszFormat, ...) +{ + int count; + + va_list args; + va_start(args, lpszFormat); + + count = wvsprintf(szText, lpszFormat, args); + va_end(args); +} + +int CardButton::Id() +{ + return id; +} + +void CardButton::Show(bool fShow) +{ + fVisible = fShow; +} + +void CardButton::Move(int x, int y, int width, int height) +{ + SetRect(&rect, x, y, x+width, y+height); +} + +void CardButton::Redraw() +{ + HDC hdc = GetDC((HWND)parentWnd); + + HPALETTE hOldPal = UseNicePalette(hdc, __hPalette); + + Draw(hdc, !fButtonDown); + + RestorePalette(hdc, hOldPal); + + ReleaseDC((HWND)parentWnd, hdc); +} + +void CardButton::SetForeColor(COLORREF cr) +{ + crText = cr; +} + +void CardButton::SetBackColor(COLORREF cr) +{ + crBack = cr; + + crHighlight = GetHighlight(cr); + crShadow = GetShadow(cr); + + //crHighlight = ScaleLumRGB(cr, +0.25); + //crShadow = ScaleLumRGB(cr, -0.25); +} + +// Static member +COLORREF CardButton::GetHighlight(COLORREF crBase) +{ + return ColorScaleRGB(crBase, RGB(255,255,255), 0.25); +} + +// Static member +COLORREF CardButton::GetShadow(COLORREF crBase) +{ + return ColorScaleRGB(crBase, RGB(0, 0, 0), 0.25); +} + +COLORREF CardButton::GetFace(COLORREF crBase) +{ + return ColorScaleRGB(crBase, RGB(255,255,255), 0.1); +} + +void CardButton::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust) +{ + xadjust = xAdjust; + yadjust = yAdjust; + xjustify = xJustify; + yjustify = yJustify; +} + +void CardButton::SetIcon(HICON hicon, bool fRedraw) +{ + hIcon = hicon; + + if(fRedraw) + Redraw(); +} + +void CardButton::SetFont(HFONT font) +{ + //don't delete the existing font.. + hFont = font; +} + +void CardButton::SetButtonProc(pButtonProc proc) +{ + ButtonCallback = proc; +} + +bool CardButton::Lock() +{ + DWORD dw = WaitForSingleObject(mxlock, 0); + + if(dw == WAIT_OBJECT_0) + return true; + else + return false; +} + +bool CardButton::UnLock() +{ + if(ReleaseMutex(mxlock)) + return true; + else + return false; +} + +void CardButton::SetStyle(UINT style) +{ + uStyle = style; +} + +UINT CardButton::GetStyle() +{ + return uStyle; +} diff --git a/rosapps/games/solitaire/cardlib/cardbutton.h b/rosapps/games/solitaire/cardlib/cardbutton.h index 9ca402ee7da..12515c44d88 100644 --- a/rosapps/games/solitaire/cardlib/cardbutton.h +++ b/rosapps/games/solitaire/cardlib/cardbutton.h @@ -1,101 +1,101 @@ -#ifndef CARDBUTTON_INCLUDED -#define CARDBUTTON_INCLUDED - -#define MAXBUTTONTEXT 64 - -#include "cardlib.h" - -class CardButton -{ - friend class CardWindow; - - // - // Constructor is PRIVATE - only a - // CardWindow can create buttons! - // - CardButton(CardWindow &parent, int id, TCHAR *szText, UINT style, bool visible, - int x, int y, int width, int height); - - ~CardButton(); - -public: - - void SetStyle(UINT uStyle); - UINT GetStyle(); - - void SetText(TCHAR *fmt, ...); - void SetFont(HFONT font); - - void SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust); - - void SetForeColor(COLORREF cr); - void SetBackColor(COLORREF cr); - - void Move(int x, int y, int width, int height); - void Show(bool fShow); - void Redraw(); - int Id(); - - void SetIcon(HICON hicon, bool fRedraw); - - void SetButtonProc(pButtonProc proc); - - CardWindow &GetCardWindow() { return parentWnd; } - - bool Lock(); - bool UnLock(); - - static COLORREF GetHighlight(COLORREF crBase); - static COLORREF GetShadow(COLORREF crBase); - static COLORREF GetFace(COLORREF crBase); - -private: - - // - // Private member functions - // - void AdjustPosition(int winwidth, int winheight); - - void DrawRect(HDC hdc, RECT *rect, bool fNormal); - void Draw(HDC hdc, bool fNormal); - void Clip(HDC hdc); - - int OnLButtonDown(HWND hwnd, int x, int y); - int OnMouseMove(HWND hwnd, int x, int y); - int OnLButtonUp(HWND hwnd, int x, int y); - - // - // Private members - // - CardWindow &parentWnd; - - RECT rect; - int id; - UINT uStyle; - bool fVisible; - - int xadjust; - int xjustify; - int yadjust; - int yjustify; - - HICON hIcon; - HFONT hFont; - - TCHAR szText[MAXBUTTONTEXT]; - - COLORREF crBack; - COLORREF crText; - COLORREF crHighlight; - COLORREF crShadow; - COLORREF crShadow2; - - bool fMouseDown; - bool fButtonDown; - - HANDLE mxlock; - - pButtonProc ButtonCallback; -}; - -#endif +#ifndef CARDBUTTON_INCLUDED +#define CARDBUTTON_INCLUDED + +#define MAXBUTTONTEXT 64 + +#include "cardlib.h" + +class CardButton +{ + friend class CardWindow; + + // + // Constructor is PRIVATE - only a + // CardWindow can create buttons! + // + CardButton(CardWindow &parent, int id, TCHAR *szText, UINT style, bool visible, + int x, int y, int width, int height); + + ~CardButton(); + +public: + + void SetStyle(UINT uStyle); + UINT GetStyle(); + + void SetText(TCHAR *fmt, ...); + void SetFont(HFONT font); + + void SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust); + + void SetForeColor(COLORREF cr); + void SetBackColor(COLORREF cr); + + void Move(int x, int y, int width, int height); + void Show(bool fShow); + void Redraw(); + int Id(); + + void SetIcon(HICON hicon, bool fRedraw); + + void SetButtonProc(pButtonProc proc); + + CardWindow &GetCardWindow() { return parentWnd; } + + bool Lock(); + bool UnLock(); + + static COLORREF GetHighlight(COLORREF crBase); + static COLORREF GetShadow(COLORREF crBase); + static COLORREF GetFace(COLORREF crBase); + +private: + + // + // Private member functions + // + void AdjustPosition(int winwidth, int winheight); + + void DrawRect(HDC hdc, RECT *rect, bool fNormal); + void Draw(HDC hdc, bool fNormal); + void Clip(HDC hdc); + + int OnLButtonDown(HWND hwnd, int x, int y); + int OnMouseMove(HWND hwnd, int x, int y); + int OnLButtonUp(HWND hwnd, int x, int y); + + // + // Private members + // + CardWindow &parentWnd; + + RECT rect; + int id; + UINT uStyle; + bool fVisible; + + int xadjust; + int xjustify; + int yadjust; + int yjustify; + + HICON hIcon; + HFONT hFont; + + TCHAR szText[MAXBUTTONTEXT]; + + COLORREF crBack; + COLORREF crText; + COLORREF crHighlight; + COLORREF crShadow; + COLORREF crShadow2; + + bool fMouseDown; + bool fButtonDown; + + HANDLE mxlock; + + pButtonProc ButtonCallback; +}; + +#endif diff --git a/rosapps/games/solitaire/cardlib/cardcolor.cpp b/rosapps/games/solitaire/cardlib/cardcolor.cpp index 1d3348a81c1..64e79605137 100644 --- a/rosapps/games/solitaire/cardlib/cardcolor.cpp +++ b/rosapps/games/solitaire/cardlib/cardcolor.cpp @@ -1,337 +1,337 @@ -// -// Colour support -// -#include - -#define MakeRGB RGB - -#define MIN3(a,b,c) ( (a)<=(b) ? (a)<=(c)?(a):(c) : (b)<=(c)?(b):(c) ) -#define MAX3(a,b,c) ( (a)>=(b) ? (a)>=(c)?(a):(c) : (b)>=(c)?(b):(c) ) - -inline double fMax(double a, double b) -{ - return a < b ? b : a; -} - -inline double fMin(double a, double b) -{ - return a < b ? a : b; -} -/****************************************************************************** - FUNCTION: RGBtoHLS - PURPOSE: Convert from RGB to HLS - IN: RGB color (0xBBGGRR) - OUT: Hue, Saturation, Luminance from 0 to 1 - COPYRIGHT:1995-1997 Robert Mashlan - Modified for LabWindows/CVI, 1999 Guillaume Dargaud -******************************************************************************/ -void RGBtoHLS(const COLORREF rgb, double *H, double *L, double *S ) -{ - double delta; - double r = (double)((rgb )&0xFF)/255; - double g = (double)((rgb>> 8)&0xFF)/255; - double b = (double)((rgb>>16)&0xFF)/255; - double cmax = MAX3(r,g,b); - double cmin = MIN3(r,g,b); - *L=(cmax+cmin)/2.0; - - if(cmax == cmin) - { - *S = *H = 0; // it's really undefined - } - else - { - if(*L < 0.5) *S = (cmax-cmin)/(cmax+cmin); - else *S = (cmax-cmin)/(2.0-cmax-cmin); - - delta = cmax - cmin; - - if(r == cmax) - { - *H = (g - b) / delta; - } - else - { - if(g == cmax) *H = 2.0 + (b-r) / delta; - else *H = 4.0 + (r-g) / delta; - } - *H /= 6.0; - if (*H < 0.0) *H += 1; - } -} - -/****************************************************************************** - FUNCTION: HueToRGB - PURPOSE: Convert a hue (color) to RGB - COPYRIGHT:1995-1997 Robert Mashlan - Modified for LabWindows/CVI, 1999 Guillaume Dargaud -******************************************************************************/ -double HueToRGB(const double m1, const double m2, double h ) -{ - if (h<0) h+=1.0; - if (h>1) h-=1.0; - if (6.0*h < 1 ) return (m1+(m2-m1)*h*6.0); - if (2.0*h < 1 ) return m2; - if (3.0*h < 2.0) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0); - return m1; -} - - -/****************************************************************************** - FUNCTION: HLStoRGB - PURPOSE: Convert from HSL to RGB - IN: Hue, Saturation, Luminance from 0 to 1 - RETURN: RGB color (0xBBGGRR) - COPYRIGHT:1995-1997 Robert Mashlan - Modified for LabWindows/CVI, 1999 Guillaume Dargaud -******************************************************************************/ - -COLORREF HLStoRGB(const double H, const double L, const double S ) -{ - double r,g,b; - double m1, m2; - - if(S == 0) - { - r = g = b = L; - } - else - { - if (L <= 0.5) - m2 = L * (1.0 + S); - else - m2 = L + S - L * S; - - m1 = 2.0 * L - m2; - - r = HueToRGB(m1,m2,H+1.0/3.0); - g = HueToRGB(m1,m2,H); - b = HueToRGB(m1,m2,H-1.0/3.0); - } - - return RGB(r*255, g*255, b*255); -} - - - -/****************************************************************************** - FUNCTION: ColorScaleHSL - PURPOSE: Returns the HSL linear interpolated color between 2 colors - (more natural looking than RGB interpolation) - For instance if the luminance is the same in Col1 and Col2, - then the luminance of the result will be the same - If Ratio=0, you get Col1, - If Ratio=1, you get Col2 - IN: Col1: low color in hex 0xBBGGRR format - Col2: high color in hex 0xBBGGRR format - Ratio: 0 for low color, 1 for high color, or in between - EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x1F5F3F -******************************************************************************/ -COLORREF ColorScaleHSL( const COLORREF Col1, const COLORREF Col2, const double Ratio) -{ - static double H1, H2, S1, S2, L1, L2; - - if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1 - else if (Ratio>=1) return Col2; - - RGBtoHLS( Col1, &H1, &L1, &S1); - RGBtoHLS( Col2, &H2, &L2, &S2); - return HLStoRGB( H1+(H2-H1)*Ratio, L1+(L2-L1)*Ratio, S1+(S2-S1)*Ratio ); -} - - -/****************************************************************************** - FUNCTION: ColorScaleRGB - PURPOSE: Returns the RGB linear interpolated color between 2 colors - If Ratio=0, you get Col1, - If Ratio=1, you get Col2 - IN: Col1: low color in hex 0xBBGGRR format - Col2: high color in hex 0xBBGGRR format - Ratio: 0 for low color, 1 for high color, or in between - EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x800080 -******************************************************************************/ -COLORREF ColorScaleRGB( const COLORREF Col1, - const COLORREF Col2, - const double Ratio) { - int R1=(Col1)&0xFF, G1=(Col1>>8)&0xFF, B1=(Col1>>16)&0xFF; - int R2=(Col2)&0xFF, G2=(Col2>>8)&0xFF, B2=(Col2>>16)&0xFF; - - if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1 - else if (Ratio>=1) return Col2; - -/* return RGB( - (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding - (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5), - (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5) - );*/ - - /*double r = Ratio; - if(Col2 == 0) - r = 1-Ratio; - else - r = 1+Ratio; - R1 = (int)(double(R1) * r + 0.5); - G1 = (int)(double(G1) * r + 0.5); - B1 = (int)(double(B1) * r + 0.5); - return RGB(R1,G1,B1);*/ - - return RGB( - (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding - (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5), - (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5) - ); -} - - - -COLORREF ColorDarker(COLORREF col, double ratio) -{ - return ColorScaleHSL(col, RGB(0,0,0), ratio); -} - -COLORREF ColorLighter(COLORREF col, double ratio) -{ - return ColorScaleHSL(col, RGB(255,255,255), ratio); -} - -// -// Experimental!!! -// -#if 0 - -typedef enum { Red, Green, Blue }; - -void RGBtoHLS(COLORREF rgb, double *Hue, double *Lum, double *Sat) -{ - double mn, mx; - int major; - - BYTE red, green, blue; - - red = GetRValue(rgb); - green = GetGValue(rgb); - blue = GetBValue(rgb); - - if(red < green) - { - mn = red; mx = green; major = Green; - } - else - { - mn = green; mx = red; major = Red; - } - - if(blue < mn) - { - mn = blue; - } - else if(blue > mx) - { - mx = blue; major = Blue; - } - - if(mn == mx) - { - *Lum = mn / 255; - *Sat = 0; - *Hue = 0; - } - else - { - *Lum = (mx + mn) / 510; - - if(*Lum <= 0.5) - *Sat = (mx-mn) / (mn+mx); - else - *Sat = (mx-mn) / (510-mn-mx); - - switch(major) - { - case Red: *Hue = (green-blue) * 60.0 / (mx-mn) + 360.0; - break; - - case Green: *Hue = (blue-red) * 60.0 / (mx-mn) + 120.0; - break; - - case Blue: *Hue = (red-green) * 60.0 / (mx-mn) + 240.0; - break; - - } - - if(*Hue > 360.0) - *Hue -= 360.0; - } -} - -static BYTE Value(double m1, double m2, double hue) -{ - - if(hue > 360) hue -= 360; - else if(hue < 0) hue += 360; - - if(hue < 60) - m1 = m1 + (m2 - m1) * hue / 60; - else if(hue < 180) - m1 = m2; - else if(hue < 240) - m1 = m1 + (m2 - m1) * (240 - hue) / 60; - - return (BYTE)(m1 * 255); -} - -COLORREF HLStoRGB(const double Hue, const double Lum, const double Sat) -{ - BYTE red, green, blue; - - if(Sat == 0) - { - red = green = blue = (BYTE)(Lum * 255); - } - else - { - double m1, m2; - - if(Lum <= 0.5) - m2 = Lum + Lum * Sat; - else - m2 = Lum + Sat - Lum * Sat; - - m1 = 2 * Lum - m2; - - red = Value(m1, m2, Hue + 120); - green = Value(m1, m2, Hue); - blue = Value(m1, m2, Hue - 120); - } - - return RGB(red, green, blue); -} - -COLORREF ScaleLumRGB(COLORREF col1, double ratio) -{ - double H1, L1, S1; - - RGBtoHLS(col1, &H1, &L1, &S1); - - L1 += L1 * ratio; - - return HLStoRGB(H1, L1, S1); -} - -COLORREF ColorScaleHSL(const COLORREF Col1, const COLORREF Col2, const double Ratio) -{ - static double H1, H2, S1, S2, L1, L2; - - if(Ratio <= 0) return Col1; // Ratio parameter must be between 0 and 1 - else if(Ratio >= 1) return Col2; - - RGBtoHLS( Col1, &H1, &L1, &S1); - RGBtoHLS( Col2, &H2, &L2, &S2); - - return HLStoRGB( H1 /*+ (H2 - H1 ) * Ratio*/, L1 + (L2 - L1) * Ratio, S1 + (S2 - S1) * Ratio * 2); -} - -COLORREF ColorScaleRGB(const COLORREF Col1, const COLORREF Col2, const double Ratio) -{ - return ColorScaleHSL(Col1, Col2, Ratio); -} -#endif +// +// Colour support +// +#include + +#define MakeRGB RGB + +#define MIN3(a,b,c) ( (a)<=(b) ? (a)<=(c)?(a):(c) : (b)<=(c)?(b):(c) ) +#define MAX3(a,b,c) ( (a)>=(b) ? (a)>=(c)?(a):(c) : (b)>=(c)?(b):(c) ) + +inline double fMax(double a, double b) +{ + return a < b ? b : a; +} + +inline double fMin(double a, double b) +{ + return a < b ? a : b; +} +/****************************************************************************** + FUNCTION: RGBtoHLS + PURPOSE: Convert from RGB to HLS + IN: RGB color (0xBBGGRR) + OUT: Hue, Saturation, Luminance from 0 to 1 + COPYRIGHT:1995-1997 Robert Mashlan + Modified for LabWindows/CVI, 1999 Guillaume Dargaud +******************************************************************************/ +void RGBtoHLS(const COLORREF rgb, double *H, double *L, double *S ) +{ + double delta; + double r = (double)((rgb )&0xFF)/255; + double g = (double)((rgb>> 8)&0xFF)/255; + double b = (double)((rgb>>16)&0xFF)/255; + double cmax = MAX3(r,g,b); + double cmin = MIN3(r,g,b); + *L=(cmax+cmin)/2.0; + + if(cmax == cmin) + { + *S = *H = 0; // it's really undefined + } + else + { + if(*L < 0.5) *S = (cmax-cmin)/(cmax+cmin); + else *S = (cmax-cmin)/(2.0-cmax-cmin); + + delta = cmax - cmin; + + if(r == cmax) + { + *H = (g - b) / delta; + } + else + { + if(g == cmax) *H = 2.0 + (b-r) / delta; + else *H = 4.0 + (r-g) / delta; + } + *H /= 6.0; + if (*H < 0.0) *H += 1; + } +} + +/****************************************************************************** + FUNCTION: HueToRGB + PURPOSE: Convert a hue (color) to RGB + COPYRIGHT:1995-1997 Robert Mashlan + Modified for LabWindows/CVI, 1999 Guillaume Dargaud +******************************************************************************/ +double HueToRGB(const double m1, const double m2, double h ) +{ + if (h<0) h+=1.0; + if (h>1) h-=1.0; + if (6.0*h < 1 ) return (m1+(m2-m1)*h*6.0); + if (2.0*h < 1 ) return m2; + if (3.0*h < 2.0) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0); + return m1; +} + + +/****************************************************************************** + FUNCTION: HLStoRGB + PURPOSE: Convert from HSL to RGB + IN: Hue, Saturation, Luminance from 0 to 1 + RETURN: RGB color (0xBBGGRR) + COPYRIGHT:1995-1997 Robert Mashlan + Modified for LabWindows/CVI, 1999 Guillaume Dargaud +******************************************************************************/ + +COLORREF HLStoRGB(const double H, const double L, const double S ) +{ + double r,g,b; + double m1, m2; + + if(S == 0) + { + r = g = b = L; + } + else + { + if (L <= 0.5) + m2 = L * (1.0 + S); + else + m2 = L + S - L * S; + + m1 = 2.0 * L - m2; + + r = HueToRGB(m1,m2,H+1.0/3.0); + g = HueToRGB(m1,m2,H); + b = HueToRGB(m1,m2,H-1.0/3.0); + } + + return RGB(r*255, g*255, b*255); +} + + + +/****************************************************************************** + FUNCTION: ColorScaleHSL + PURPOSE: Returns the HSL linear interpolated color between 2 colors + (more natural looking than RGB interpolation) + For instance if the luminance is the same in Col1 and Col2, + then the luminance of the result will be the same + If Ratio=0, you get Col1, + If Ratio=1, you get Col2 + IN: Col1: low color in hex 0xBBGGRR format + Col2: high color in hex 0xBBGGRR format + Ratio: 0 for low color, 1 for high color, or in between + EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x1F5F3F +******************************************************************************/ +COLORREF ColorScaleHSL( const COLORREF Col1, const COLORREF Col2, const double Ratio) +{ + static double H1, H2, S1, S2, L1, L2; + + if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1 + else if (Ratio>=1) return Col2; + + RGBtoHLS( Col1, &H1, &L1, &S1); + RGBtoHLS( Col2, &H2, &L2, &S2); + return HLStoRGB( H1+(H2-H1)*Ratio, L1+(L2-L1)*Ratio, S1+(S2-S1)*Ratio ); +} + + +/****************************************************************************** + FUNCTION: ColorScaleRGB + PURPOSE: Returns the RGB linear interpolated color between 2 colors + If Ratio=0, you get Col1, + If Ratio=1, you get Col2 + IN: Col1: low color in hex 0xBBGGRR format + Col2: high color in hex 0xBBGGRR format + Ratio: 0 for low color, 1 for high color, or in between + EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x800080 +******************************************************************************/ +COLORREF ColorScaleRGB( const COLORREF Col1, + const COLORREF Col2, + const double Ratio) { + int R1=(Col1)&0xFF, G1=(Col1>>8)&0xFF, B1=(Col1>>16)&0xFF; + int R2=(Col2)&0xFF, G2=(Col2>>8)&0xFF, B2=(Col2>>16)&0xFF; + + if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1 + else if (Ratio>=1) return Col2; + +/* return RGB( + (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding + (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5), + (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5) + );*/ + + /*double r = Ratio; + if(Col2 == 0) + r = 1-Ratio; + else + r = 1+Ratio; + R1 = (int)(double(R1) * r + 0.5); + G1 = (int)(double(G1) * r + 0.5); + B1 = (int)(double(B1) * r + 0.5); + return RGB(R1,G1,B1);*/ + + return RGB( + (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding + (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5), + (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5) + ); +} + + + +COLORREF ColorDarker(COLORREF col, double ratio) +{ + return ColorScaleHSL(col, RGB(0,0,0), ratio); +} + +COLORREF ColorLighter(COLORREF col, double ratio) +{ + return ColorScaleHSL(col, RGB(255,255,255), ratio); +} + +// +// Experimental!!! +// +#if 0 + +typedef enum { Red, Green, Blue }; + +void RGBtoHLS(COLORREF rgb, double *Hue, double *Lum, double *Sat) +{ + double mn, mx; + int major; + + BYTE red, green, blue; + + red = GetRValue(rgb); + green = GetGValue(rgb); + blue = GetBValue(rgb); + + if(red < green) + { + mn = red; mx = green; major = Green; + } + else + { + mn = green; mx = red; major = Red; + } + + if(blue < mn) + { + mn = blue; + } + else if(blue > mx) + { + mx = blue; major = Blue; + } + + if(mn == mx) + { + *Lum = mn / 255; + *Sat = 0; + *Hue = 0; + } + else + { + *Lum = (mx + mn) / 510; + + if(*Lum <= 0.5) + *Sat = (mx-mn) / (mn+mx); + else + *Sat = (mx-mn) / (510-mn-mx); + + switch(major) + { + case Red: *Hue = (green-blue) * 60.0 / (mx-mn) + 360.0; + break; + + case Green: *Hue = (blue-red) * 60.0 / (mx-mn) + 120.0; + break; + + case Blue: *Hue = (red-green) * 60.0 / (mx-mn) + 240.0; + break; + + } + + if(*Hue > 360.0) + *Hue -= 360.0; + } +} + +static BYTE Value(double m1, double m2, double hue) +{ + + if(hue > 360) hue -= 360; + else if(hue < 0) hue += 360; + + if(hue < 60) + m1 = m1 + (m2 - m1) * hue / 60; + else if(hue < 180) + m1 = m2; + else if(hue < 240) + m1 = m1 + (m2 - m1) * (240 - hue) / 60; + + return (BYTE)(m1 * 255); +} + +COLORREF HLStoRGB(const double Hue, const double Lum, const double Sat) +{ + BYTE red, green, blue; + + if(Sat == 0) + { + red = green = blue = (BYTE)(Lum * 255); + } + else + { + double m1, m2; + + if(Lum <= 0.5) + m2 = Lum + Lum * Sat; + else + m2 = Lum + Sat - Lum * Sat; + + m1 = 2 * Lum - m2; + + red = Value(m1, m2, Hue + 120); + green = Value(m1, m2, Hue); + blue = Value(m1, m2, Hue - 120); + } + + return RGB(red, green, blue); +} + +COLORREF ScaleLumRGB(COLORREF col1, double ratio) +{ + double H1, L1, S1; + + RGBtoHLS(col1, &H1, &L1, &S1); + + L1 += L1 * ratio; + + return HLStoRGB(H1, L1, S1); +} + +COLORREF ColorScaleHSL(const COLORREF Col1, const COLORREF Col2, const double Ratio) +{ + static double H1, H2, S1, S2, L1, L2; + + if(Ratio <= 0) return Col1; // Ratio parameter must be between 0 and 1 + else if(Ratio >= 1) return Col2; + + RGBtoHLS( Col1, &H1, &L1, &S1); + RGBtoHLS( Col2, &H2, &L2, &S2); + + return HLStoRGB( H1 /*+ (H2 - H1 ) * Ratio*/, L1 + (L2 - L1) * Ratio, S1 + (S2 - S1) * Ratio * 2); +} + +COLORREF ColorScaleRGB(const COLORREF Col1, const COLORREF Col2, const double Ratio) +{ + return ColorScaleHSL(Col1, Col2, Ratio); +} +#endif diff --git a/rosapps/games/solitaire/cardlib/cardcolor.h b/rosapps/games/solitaire/cardlib/cardcolor.h index d97adce8471..e8a9ff21ff9 100644 --- a/rosapps/games/solitaire/cardlib/cardcolor.h +++ b/rosapps/games/solitaire/cardlib/cardcolor.h @@ -1,16 +1,16 @@ - -COLORREF ColorScaleRGB( const COLORREF Col1, - const COLORREF Col2, - const double Ratio); - -COLORREF ColorScaleHSL( const COLORREF Col1, - const COLORREF Col2, - const double Ratio); - - -COLORREF ColorDarker(COLORREF col, double ratio); -COLORREF ColorLighter(COLORREF col, double ratio); - -COLORREF ScaleLumRGB(COLORREF col1, double ratio); - -#define MAKE_PALETTERGB(colref) (0x02000000 | colref) + +COLORREF ColorScaleRGB( const COLORREF Col1, + const COLORREF Col2, + const double Ratio); + +COLORREF ColorScaleHSL( const COLORREF Col1, + const COLORREF Col2, + const double Ratio); + + +COLORREF ColorDarker(COLORREF col, double ratio); +COLORREF ColorLighter(COLORREF col, double ratio); + +COLORREF ScaleLumRGB(COLORREF col1, double ratio); + +#define MAKE_PALETTERGB(colref) (0x02000000 | colref) diff --git a/rosapps/games/solitaire/cardlib/cardcount.cpp b/rosapps/games/solitaire/cardlib/cardcount.cpp index 7321858abd0..5cafdd22c61 100644 --- a/rosapps/games/solitaire/cardlib/cardcount.cpp +++ b/rosapps/games/solitaire/cardlib/cardcount.cpp @@ -1,90 +1,90 @@ -// -// CardCount is a helper library for CardStacks. -// -// When you initialize a CardCount object with a -// cardstack, it keeps track of the number of cards -// the stack contains. -// -// e.g. CardCount count(cardstack); -// -// Then you can do: -// -// int num_fives = count[5] -// -// count.Add(cardstack2); - combine with another stack -// -// int num_aces = count[1] - aces low -// int num_aces = count[14] - aces high -// -// count.Clear(); -// -#include "cardcount.h" - -CardCount::CardCount() -{ - Clear(); -} - -CardCount::CardCount(const CardStack &cs) -{ - Init(cs); -} - -void CardCount::Clear() -{ - for(int i = 0; i < 13; i++) - count[i] = 0; -} - -void CardCount::Add(const CardStack &cs) -{ - for(int i = 0; i < cs.NumCards(); i++) - { - Card card = cs[i]; - - int val = card.LoVal(); - count[val - 1]++; - } -} - -void CardCount::Sub(const CardStack &cs) -{ - for(int i = 0; i < cs.NumCards(); i++) - { - Card card = cs[i]; - int val = card.LoVal(); - - if(count[val - 1] > 0) - count[val - 1]--; - } -} - -void CardCount::Init(const CardStack &cs) -{ - Clear(); - Add(cs); -} - -int CardCount::operator [] (size_t index) const -{ - if(index < 1) return 0; - else if(index > 14) return 0; //if out of range - else if(index == 14) index = 1; //if a "ace-high" - - return count[index - 1]; -} - -// -// Decrement specified item by one -// -void CardCount::Dec(size_t index) -{ - if(index < 1) return; - else if(index > 14) return; //if out of range - else if(index == 14) index = 1; //if a "ace-high" - - index -= 1; - - if(count[index] > 0) - count[index]--; -} +// +// CardCount is a helper library for CardStacks. +// +// When you initialize a CardCount object with a +// cardstack, it keeps track of the number of cards +// the stack contains. +// +// e.g. CardCount count(cardstack); +// +// Then you can do: +// +// int num_fives = count[5] +// +// count.Add(cardstack2); - combine with another stack +// +// int num_aces = count[1] - aces low +// int num_aces = count[14] - aces high +// +// count.Clear(); +// +#include "cardcount.h" + +CardCount::CardCount() +{ + Clear(); +} + +CardCount::CardCount(const CardStack &cs) +{ + Init(cs); +} + +void CardCount::Clear() +{ + for(int i = 0; i < 13; i++) + count[i] = 0; +} + +void CardCount::Add(const CardStack &cs) +{ + for(int i = 0; i < cs.NumCards(); i++) + { + Card card = cs[i]; + + int val = card.LoVal(); + count[val - 1]++; + } +} + +void CardCount::Sub(const CardStack &cs) +{ + for(int i = 0; i < cs.NumCards(); i++) + { + Card card = cs[i]; + int val = card.LoVal(); + + if(count[val - 1] > 0) + count[val - 1]--; + } +} + +void CardCount::Init(const CardStack &cs) +{ + Clear(); + Add(cs); +} + +int CardCount::operator [] (size_t index) const +{ + if(index < 1) return 0; + else if(index > 14) return 0; //if out of range + else if(index == 14) index = 1; //if a "ace-high" + + return count[index - 1]; +} + +// +// Decrement specified item by one +// +void CardCount::Dec(size_t index) +{ + if(index < 1) return; + else if(index > 14) return; //if out of range + else if(index == 14) index = 1; //if a "ace-high" + + index -= 1; + + if(count[index] > 0) + count[index]--; +} diff --git a/rosapps/games/solitaire/cardlib/cardcount.h b/rosapps/games/solitaire/cardlib/cardcount.h index f97ba153151..6e0a632c522 100644 --- a/rosapps/games/solitaire/cardlib/cardcount.h +++ b/rosapps/games/solitaire/cardlib/cardcount.h @@ -1,31 +1,31 @@ -#ifndef _CARDCOUNT_INCLUDED -#define _CARDCOUNT_INCLUDED - -#include - -#include "cardstack.h" - -class CardCount -{ -public: - CardCount(); - CardCount(const CardStack &cs); - - void Init(const CardStack &cs); - void Clear(); - void Add(const CardStack &cs); - void Sub(const CardStack &cs); - - void Dec(size_t index); - - int operator[] (size_t index) const; - - CardCount &operator = (const CardStack &cs); - CardCount &operator += (const CardStack &cs); - -private: - int count[13]; //13 different card values - //(ace,2,3,4,5,6,7,8,9,10,J,Q,K) -}; - -#endif +#ifndef _CARDCOUNT_INCLUDED +#define _CARDCOUNT_INCLUDED + +#include + +#include "cardstack.h" + +class CardCount +{ +public: + CardCount(); + CardCount(const CardStack &cs); + + void Init(const CardStack &cs); + void Clear(); + void Add(const CardStack &cs); + void Sub(const CardStack &cs); + + void Dec(size_t index); + + int operator[] (size_t index) const; + + CardCount &operator = (const CardStack &cs); + CardCount &operator += (const CardStack &cs); + +private: + int count[13]; //13 different card values + //(ace,2,3,4,5,6,7,8,9,10,J,Q,K) +}; + +#endif diff --git a/rosapps/games/solitaire/cardlib/cardlib.cpp b/rosapps/games/solitaire/cardlib/cardlib.cpp index acd37c0c92c..dcbe424477f 100644 --- a/rosapps/games/solitaire/cardlib/cardlib.cpp +++ b/rosapps/games/solitaire/cardlib/cardlib.cpp @@ -1,122 +1,122 @@ -// -// CardLib - not much of interest in here -// -// Freeware -// Copyright J Brown 2001 -// -#include -#include "cardlib.h" -#include "globals.h" - -void LoadCardBitmaps(void); - -//static bool __CARDLIB_ACES_HIGH = false; -extern double __CARDZOOMSPEED; - -// -// Global variables! -// -HDC __hdcCardBitmaps; -HBITMAP __hbmCardBitmaps; - -HDC __hdcPlaceHolder; -HBITMAP __hbmPlaceHolder; -HPALETTE __holdplacepal; - -int __cardwidth; -int __cardheight; - -HPALETTE __hPalette; - - -// -// Cardlib global functions! -// -void CardLib_SetZoomSpeed(int speed) -{ - __CARDZOOMSPEED = (double)speed; -} - -/* - - It's dangerous to use these operators, because of all - the implicit conversions that could take place, which - would have unpredicted side-effects. - - e.g. Card card(Hearts, 4); - if(card == 4) - how does 4 get converted?? - It uses the Card(int uval) constructor, - which results in a 2 of clubs... - not what was expected -*/ -/* -void CardLib_SetAcesHigh(bool fHigh); -bool operator != (const Card &lhs, const Card &rhs); -bool operator == (const Card &lhs, const Card &rhs); -bool operator < (const Card &lhs, const Card &rhs); -bool operator <= (const Card &lhs, const Card &rhs); -bool operator > (const Card &lhs, const Card &rhs); -bool operator >= (const Card &lhs, const Card &rhs); -*/ - -/* -void CardLib_SetAcesHigh(bool fHigh) -{ - __CARDLIB_ACES_HIGH = fHigh; -} - -bool operator == (const Card &lhs, const Card &rhs) -{ - if(__CARDLIB_ACES_HIGH) - return lhs.HiVal() == rhs.HiVal(); - else - return lhs.LoVal() == rhs.LoVal(); -} - -bool operator != (const Card &lhs, const Card &rhs) -{ - if(__CARDLIB_ACES_HIGH) - return lhs.HiVal() != rhs.HiVal(); - else - return lhs.LoVal() != rhs.LoVal(); -} - -bool operator > (const Card &lhs, const Card &rhs) -{ - if(__CARDLIB_ACES_HIGH) - return lhs.HiVal() > rhs.HiVal(); - else - return lhs.LoVal() > rhs.LoVal(); -} - -bool operator >= (const Card &lhs, const Card &rhs) -{ - if(__CARDLIB_ACES_HIGH) - return lhs.HiVal() >= rhs.HiVal(); - else - return lhs.LoVal() >= rhs.LoVal(); -} - -bool operator < (const Card &lhs, const Card &rhs) -{ - if(__CARDLIB_ACES_HIGH) - return lhs.HiVal() < rhs.HiVal(); - else - return lhs.LoVal() < rhs.LoVal(); -} - -bool operator <= (const Card &lhs, const Card &rhs) -{ - if(__CARDLIB_ACES_HIGH) - return lhs.HiVal() <= rhs.HiVal(); - else - return lhs.LoVal() <= rhs.LoVal(); -} -*/ - -void PaintRect(HDC hdc, RECT *rect, COLORREF colour) -{ - COLORREF oldcr = SetBkColor(hdc, colour); - ExtTextOut(hdc, 0, 0, ETO_OPAQUE, rect, "", 0, 0); - SetBkColor(hdc, oldcr); -} +// +// CardLib - not much of interest in here +// +// Freeware +// Copyright J Brown 2001 +// +#include +#include "cardlib.h" +#include "globals.h" + +void LoadCardBitmaps(void); + +//static bool __CARDLIB_ACES_HIGH = false; +extern double __CARDZOOMSPEED; + +// +// Global variables! +// +HDC __hdcCardBitmaps; +HBITMAP __hbmCardBitmaps; + +HDC __hdcPlaceHolder; +HBITMAP __hbmPlaceHolder; +HPALETTE __holdplacepal; + +int __cardwidth; +int __cardheight; + +HPALETTE __hPalette; + + +// +// Cardlib global functions! +// +void CardLib_SetZoomSpeed(int speed) +{ + __CARDZOOMSPEED = (double)speed; +} + +/* + + It's dangerous to use these operators, because of all + the implicit conversions that could take place, which + would have unpredicted side-effects. + + e.g. Card card(Hearts, 4); + if(card == 4) - how does 4 get converted?? + It uses the Card(int uval) constructor, + which results in a 2 of clubs... + not what was expected +*/ +/* +void CardLib_SetAcesHigh(bool fHigh); +bool operator != (const Card &lhs, const Card &rhs); +bool operator == (const Card &lhs, const Card &rhs); +bool operator < (const Card &lhs, const Card &rhs); +bool operator <= (const Card &lhs, const Card &rhs); +bool operator > (const Card &lhs, const Card &rhs); +bool operator >= (const Card &lhs, const Card &rhs); +*/ + +/* +void CardLib_SetAcesHigh(bool fHigh) +{ + __CARDLIB_ACES_HIGH = fHigh; +} + +bool operator == (const Card &lhs, const Card &rhs) +{ + if(__CARDLIB_ACES_HIGH) + return lhs.HiVal() == rhs.HiVal(); + else + return lhs.LoVal() == rhs.LoVal(); +} + +bool operator != (const Card &lhs, const Card &rhs) +{ + if(__CARDLIB_ACES_HIGH) + return lhs.HiVal() != rhs.HiVal(); + else + return lhs.LoVal() != rhs.LoVal(); +} + +bool operator > (const Card &lhs, const Card &rhs) +{ + if(__CARDLIB_ACES_HIGH) + return lhs.HiVal() > rhs.HiVal(); + else + return lhs.LoVal() > rhs.LoVal(); +} + +bool operator >= (const Card &lhs, const Card &rhs) +{ + if(__CARDLIB_ACES_HIGH) + return lhs.HiVal() >= rhs.HiVal(); + else + return lhs.LoVal() >= rhs.LoVal(); +} + +bool operator < (const Card &lhs, const Card &rhs) +{ + if(__CARDLIB_ACES_HIGH) + return lhs.HiVal() < rhs.HiVal(); + else + return lhs.LoVal() < rhs.LoVal(); +} + +bool operator <= (const Card &lhs, const Card &rhs) +{ + if(__CARDLIB_ACES_HIGH) + return lhs.HiVal() <= rhs.HiVal(); + else + return lhs.LoVal() <= rhs.LoVal(); +} +*/ + +void PaintRect(HDC hdc, RECT *rect, COLORREF colour) +{ + COLORREF oldcr = SetBkColor(hdc, colour); + ExtTextOut(hdc, 0, 0, ETO_OPAQUE, rect, "", 0, 0); + SetBkColor(hdc, oldcr); +} diff --git a/rosapps/games/solitaire/cardlib/cardlib.h b/rosapps/games/solitaire/cardlib/cardlib.h index ee0ab4ad072..33f5c02540d 100644 --- a/rosapps/games/solitaire/cardlib/cardlib.h +++ b/rosapps/games/solitaire/cardlib/cardlib.h @@ -1,102 +1,102 @@ -#ifndef CARDLIB_INCLUDED -#define CARDLIB_INCLUDED - -#define CARDLIBPROC __stdcall - -void CardBlt(HDC hdc, int x, int y, int nCardNum); -void CardLib_SetZoomSpeed(int); - -#define CS_EI_NONE 0 -#define CS_EI_SUNK 1 - -#define CS_DEFXOFF 12 //x-offset -#define CS_DEFYOFF 18 //y-offset -#define CS_NO3D 1 //default 3d counts (recommened) -#define CS_DEF3D 10 //(best for decks) - -//#define CS_EI_CIRC 2 -//#define CS_EI_X 3 - -#define CS_DRAG_NONE 0 -#define CS_DRAG_TOP 1 -#define CS_DRAG_ALL 2 -#define CS_DRAG_CALLBACK 3 - -#define CS_DROP_NONE 0 -#define CS_DROP_ALL 1 -#define CS_DROP_CALLBACK 2 - -#define CS_XJUST_NONE 0 -#define CS_XJUST_RIGHT 1 -#define CS_XJUST_CENTER 2 - -#define CS_YJUST_NONE 0 -#define CS_YJUST_BOTTOM 1 -#define CS_YJUST_CENTER 2 - -#define CB_STATIC 0 //static text label -#define CB_PUSHBUTTON 1 //normal button -#define CB_ALIGN_CENTER 0 //centered is default -#define CB_ALIGN_LEFT 2 -#define CB_ALIGN_RIGHT 4 - -#define CS_FACE_UP 0 //all cards face-up -#define CS_FACE_DOWN 1 //all cards face-down -#define CS_FACE_DOWNUP 2 //bottom X cards down, top-most face-up -#define CS_FACE_UPDOWN 3 //bottom X cards up, top-most face-down -#define CS_FACE_ANY 4 //cards can be any orientation - -#define CS_DROPZONE_NODROP -1 - -// -// Define the standard card-back indices -// -#define ecbCROSSHATCH 53 -#define ecbWEAVE1 54 -#define ecbWEAVE2 55 -#define ecbROBOT 56 -#define ecbFLOWERS 57 -#define ecbVINE1 58 -#define ecbVINE2 59 -#define ecbFISH1 60 -#define ecbFISH2 61 -#define ecbSHELLS 62 -#define ecbCASTLE 63 -#define ecbISLAND 64 -#define ecbCARDHAND 65 -#define ecbUNUSED 66 -#define ecbTHE_X 67 -#define ecbTHE_O 68 - - -class CardRegion; -class CardButton; -class CardStack; -class CardWindow; - -typedef bool (CARDLIBPROC *pCanDragProc) (CardRegion &stackobj, int iNumDragging); -typedef bool (CARDLIBPROC *pCanDropProc) (CardRegion &stackobj, const CardStack &cards); -typedef void (CARDLIBPROC *pClickProc) (CardRegion &stackobj, int iNumCards); -typedef void (CARDLIBPROC *pAddProc) (CardRegion &stackobj, const CardStack &cards); -typedef void (CARDLIBPROC *pRemoveProc) (CardRegion &stackobj, int iNumRemoved); - -typedef void (CARDLIBPROC *pResizeWndProc) (int width, int height); -typedef int (CARDLIBPROC *pDropZoneProc) (int dzid, const CardStack &cards); - -typedef void (CARDLIBPROC *pButtonProc) (CardButton &pButton); - - -#include "card.h" -#include "cardbutton.h" -#include "cardstack.h" -#include "cardregion.h" -#include "cardcount.h" -#include "cardwindow.h" - -#ifdef _DEBUG -typedef bool (CARDLIBPROC *pDebugClickProc) (CardRegion &stackobj); -void CardLib_SetStackClickProc(pDebugClickProc proc); -#endif - - -#endif +#ifndef CARDLIB_INCLUDED +#define CARDLIB_INCLUDED + +#define CARDLIBPROC __stdcall + +void CardBlt(HDC hdc, int x, int y, int nCardNum); +void CardLib_SetZoomSpeed(int); + +#define CS_EI_NONE 0 +#define CS_EI_SUNK 1 + +#define CS_DEFXOFF 12 //x-offset +#define CS_DEFYOFF 18 //y-offset +#define CS_NO3D 1 //default 3d counts (recommened) +#define CS_DEF3D 10 //(best for decks) + +//#define CS_EI_CIRC 2 +//#define CS_EI_X 3 + +#define CS_DRAG_NONE 0 +#define CS_DRAG_TOP 1 +#define CS_DRAG_ALL 2 +#define CS_DRAG_CALLBACK 3 + +#define CS_DROP_NONE 0 +#define CS_DROP_ALL 1 +#define CS_DROP_CALLBACK 2 + +#define CS_XJUST_NONE 0 +#define CS_XJUST_RIGHT 1 +#define CS_XJUST_CENTER 2 + +#define CS_YJUST_NONE 0 +#define CS_YJUST_BOTTOM 1 +#define CS_YJUST_CENTER 2 + +#define CB_STATIC 0 //static text label +#define CB_PUSHBUTTON 1 //normal button +#define CB_ALIGN_CENTER 0 //centered is default +#define CB_ALIGN_LEFT 2 +#define CB_ALIGN_RIGHT 4 + +#define CS_FACE_UP 0 //all cards face-up +#define CS_FACE_DOWN 1 //all cards face-down +#define CS_FACE_DOWNUP 2 //bottom X cards down, top-most face-up +#define CS_FACE_UPDOWN 3 //bottom X cards up, top-most face-down +#define CS_FACE_ANY 4 //cards can be any orientation + +#define CS_DROPZONE_NODROP -1 + +// +// Define the standard card-back indices +// +#define ecbCROSSHATCH 53 +#define ecbWEAVE1 54 +#define ecbWEAVE2 55 +#define ecbROBOT 56 +#define ecbFLOWERS 57 +#define ecbVINE1 58 +#define ecbVINE2 59 +#define ecbFISH1 60 +#define ecbFISH2 61 +#define ecbSHELLS 62 +#define ecbCASTLE 63 +#define ecbISLAND 64 +#define ecbCARDHAND 65 +#define ecbUNUSED 66 +#define ecbTHE_X 67 +#define ecbTHE_O 68 + + +class CardRegion; +class CardButton; +class CardStack; +class CardWindow; + +typedef bool (CARDLIBPROC *pCanDragProc) (CardRegion &stackobj, int iNumDragging); +typedef bool (CARDLIBPROC *pCanDropProc) (CardRegion &stackobj, const CardStack &cards); +typedef void (CARDLIBPROC *pClickProc) (CardRegion &stackobj, int iNumCards); +typedef void (CARDLIBPROC *pAddProc) (CardRegion &stackobj, const CardStack &cards); +typedef void (CARDLIBPROC *pRemoveProc) (CardRegion &stackobj, int iNumRemoved); + +typedef void (CARDLIBPROC *pResizeWndProc) (int width, int height); +typedef int (CARDLIBPROC *pDropZoneProc) (int dzid, const CardStack &cards); + +typedef void (CARDLIBPROC *pButtonProc) (CardButton &pButton); + + +#include "card.h" +#include "cardbutton.h" +#include "cardstack.h" +#include "cardregion.h" +#include "cardcount.h" +#include "cardwindow.h" + +#ifdef _DEBUG +typedef bool (CARDLIBPROC *pDebugClickProc) (CardRegion &stackobj); +void CardLib_SetStackClickProc(pDebugClickProc proc); +#endif + + +#endif diff --git a/rosapps/games/solitaire/cardlib/cardregion.cpp b/rosapps/games/solitaire/cardlib/cardregion.cpp index 5eb1c3f4a34..b37d0866fca 100644 --- a/rosapps/games/solitaire/cardlib/cardregion.cpp +++ b/rosapps/games/solitaire/cardlib/cardregion.cpp @@ -1,658 +1,658 @@ -// -// CardLib - CardRegion class -// -// Freeware -// Copyright J Brown 2001 -// -#include - -#include "cardlib.h" -#include "cardregion.h" -#include "cardwindow.h" -#include "cardcolor.h" - -HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, int width, int height); - -void PaintRect(HDC hdc, RECT *rect, COLORREF colour); - -CardRegion::CardRegion(CardWindow &parent, int Id, bool visible, int x, int y, int xOffset, int yOffset) -: id(Id), parentWnd(parent), xpos(x), ypos(y), xoffset(xOffset), yoffset(yOffset), fVisible(visible) -{ - width = __cardwidth; - height = __cardheight; - - crBackgnd = RGB(0, 64, 100); - - uFaceDirType = CS_FACE_UP; - nFaceDirOption = 0; - uEmptyImage = CS_EI_SUNK; - - fVisible = visible; - - nThreedCount = 1; - nBackCardIdx = 53; - - Update(); //Update this stack's size+card count - - hdcBackGnd = 0; - hbmBackGnd = 0; - hdcDragCard = 0; - hbmDragCard = 0; - - nDragCardWidth = 0; - nDragCardHeight = 0; - - CanDragCallback = 0; - CanDropCallback = 0; - AddCallback = 0; - RemoveCallback = 0; - ClickCallback = 0; - DblClickCallback = 0; - - uDragRule = CS_DRAG_ALL; - uDropRule = CS_DROP_ALL; - - xjustify = yjustify = xadjust = yadjust = 0; - - nFlashCount = 0; - fFlashVisible = false; - uFlashTimer = (UINT)-1; - - fMouseDragging = false; - - mxlock = CreateMutex(0, FALSE, 0); -} - -CardRegion::~CardRegion() -{ - CloseHandle(mxlock); -} - -void CardRegion::SetBackColor(COLORREF cr) -{ - crBackgnd = cr; -} - -int CardRegion::CalcApparentCards(int realnum) -{ - return ((realnum + nThreedCount - 1) - (realnum + nThreedCount - 1) % nThreedCount) / nThreedCount; -} - -void CardRegion::CalcApparentCards() -{ - nNumApparentCards = CalcApparentCards(cardstack.NumCards()); -} - - -void CardRegion::UpdateSize(void) -{ - if(cardstack.NumCards() > 0) - { - if(xoffset > 0) - width = (nNumApparentCards - 1) * xoffset + __cardwidth; - else - width = (nNumApparentCards - 1) * -xoffset + __cardwidth; - - if(yoffset > 0) - height = (nNumApparentCards - 1) * yoffset + __cardheight; - else - height = (nNumApparentCards - 1) * -yoffset + __cardheight; - } - else - { - width = __cardwidth; - height = __cardheight; - } -} - -CardRegion *CardWindow::CreateRegion(int id, bool fVisible, int x, int y, int xoffset, int yoffset) -{ - CardRegion *cr; - - if(nNumCardRegions == MAXCARDSTACKS) - return FALSE; - - cr = new CardRegion(*this, id, fVisible, x, y, xoffset, yoffset); - cr->SetBackColor(crBackgnd); - cr->SetBackCardIdx(nBackCardIdx); - - Regions[nNumCardRegions++] = cr; - - return cr; -} - -int CardRegion::GetOverlapRatio(int x, int y, int w, int h) -{ - RECT me, him; - RECT inter; - SetRect(&him, x, y, x+w, y+h); - SetRect(&me, xpos, ypos, xpos+width, ypos+height); - - //see if the specified rectangle overlaps us - if(IntersectRect(&inter, &me, &him)) - { - int wi = inter.right - inter.left; - int hi = inter.bottom - inter.top; - - int overlap = wi * hi; - int total = width * height; - - int percent = (overlap << 16) / total; - return (percent * 100) >> 16; - } - //do not overlap - else - { - return 0; - } -} - -bool CardRegion::SetDragRule(UINT uDragType, pCanDragProc proc) -{ - switch(uDragType) - { - case CS_DRAG_NONE: case CS_DRAG_ALL: case CS_DRAG_TOP: - uDragRule = uDragType; - return true; - - case CS_DRAG_CALLBACK: - uDragRule = uDragType; - CanDragCallback = proc; - return true; - - default: - return false; - } -} - -bool CardRegion::SetDropRule(UINT uDropType, pCanDropProc proc) -{ - switch(uDropType) - { - case CS_DROP_NONE: case CS_DROP_ALL: - uDropRule = uDropType; - return true; - - case CS_DROP_CALLBACK: - uDropRule = uDropType; - CanDropCallback = proc; - return true; - - default: - return false; - } -} - -void CardRegion::SetClickProc(pClickProc proc) -{ - ClickCallback = proc; -} - -void CardRegion::SetDblClickProc(pClickProc proc) -{ - DblClickCallback = proc; -} - -void CardRegion::SetAddCardProc(pAddProc proc) -{ - AddCallback = proc; -} - -void CardRegion::SetRemoveCardProc(pRemoveProc proc) -{ - RemoveCallback = proc; -} - -void CardRegion::Update() -{ - CalcApparentCards(); - UpdateSize(); - UpdateFaceDir(cardstack); -} - - -bool CardRegion::SetThreedCount(int count) -{ - if(count < 1) - { - return false; - } - else - { - nThreedCount = count; - return true; - } -} - -void CardRegion::SetOffsets(int x, int y) -{ - xoffset = x; - yoffset = y; -} - -void CardRegion::SetPos(int x, int y) -{ - xpos = x; - ypos = y; -} - -void CardRegion::Show(bool fShow) -{ - fVisible = fShow; -} - -bool CardRegion::IsVisible() -{ - return fVisible; -} - -void CardRegion::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust) -{ - xjustify = xJustify; - yjustify = yJustify; - xadjust = xAdjust; - yadjust = yAdjust; -} - -void CardRegion::SetFaceDirection(UINT uDirType, int nOption) -{ - switch(uDirType) - { - case CS_FACE_UP: case CS_FACE_DOWN: case CS_FACE_DOWNUP: - case CS_FACE_UPDOWN: case CS_FACE_ANY: - uFaceDirType = uDirType; - nFaceDirOption = nOption; - - UpdateFaceDir(cardstack); - - break; - } -} - -UINT CardRegion::GetFaceDirection(int *pnOption) -{ - if(pnOption) - *pnOption = nFaceDirOption; - - return uFaceDirType; -} - -void CardRegion::AdjustPosition(int winwidth, int winheight) -{ - Update(); //Update this stack's card count + size - - switch(xjustify) - { - default: case CS_XJUST_NONE: break; - - case CS_XJUST_CENTER: //centered - xpos = (winwidth - (width & ~0x1)) / 2; - xpos += xadjust; - - if(xoffset < 0) xpos += (width - __cardwidth); - - break; - - case CS_XJUST_RIGHT: //right-aligned - xpos = winwidth - __cardwidth;//width - 20; - xpos += xadjust; - break; - } - - switch(yjustify) - { - default: case CS_YJUST_NONE: break; - - case CS_YJUST_CENTER: //centered - ypos = (winheight - height) / 2; - ypos += yadjust; - if(yoffset < 0) ypos += (height - __cardheight); - break; - - case CS_YJUST_BOTTOM: //bottom-aligned - ypos = winheight - __cardheight;//height - 20; - ypos += yadjust; - break; - } - -} - - -void CardRegion::Flash(int count, int milliseconds) -{ - if(count <= 0) return; - - nFlashCount = count; - fFlashVisible = false; - uFlashTimer = SetTimer((HWND)parentWnd, (WPARAM)this, milliseconds, 0); - - parentWnd.Redraw(); -} - -void CardRegion::StopFlash() -{ - if(uFlashTimer != (UINT)-1) - { - KillTimer((HWND)parentWnd, uFlashTimer); - nFlashCount = 0; - uFlashTimer = (UINT)-1; - fFlashVisible = true; - } -} - -void CardRegion::DoFlash() -{ - if(uFlashTimer != (UINT)-1) - { - fFlashVisible = !fFlashVisible; - - if(--nFlashCount == 0) - { - KillTimer((HWND)parentWnd, uFlashTimer); - uFlashTimer = (UINT)-1; - fFlashVisible = true; - } - - parentWnd.Redraw(); - } -} - -int CardRegion::Id() -{ - return id; -} - -void CardRegion::SetEmptyImage(UINT uImage) -{ - switch(uImage) - { - case CS_EI_NONE: case CS_EI_SUNK: - uEmptyImage = uImage; - break; - - default: - uEmptyImage = CS_EI_NONE; - break; - } - -} - -void CardRegion::SetBackCardIdx(UINT uBackIdx) -{ - if(uBackIdx >= 52 && uBackIdx <= 68) - nBackCardIdx = uBackIdx; -} - -void CardRegion::SetCardStack(const CardStack &cs) -{ - //make a complete copy of the specified stack.. - cardstack = cs; - - // Update the face-direction and stack-size - Update(); -} - -const CardStack & CardRegion::GetCardStack() -{ - //return reference to our internal stack - return cardstack; -} - -// -// Update specified card-stack using THIS stack's -// face direction rules! -// -void CardRegion::UpdateFaceDir(CardStack &cards) -{ - int i, n, num; - - num = cards.NumCards(); - - //Now apply the face direction rules.. - switch(uFaceDirType) - { - case CS_FACE_UP: - - for(i = 0; i < num; i++) - { - cards[i].SetFaceUp(true); - } - - break; - - case CS_FACE_DOWN: - - for(i = 0; i < num; i++) - { - cards[i].SetFaceUp(false); - } - - break; - - case CS_FACE_DOWNUP: - - num = cardstack.NumCards(); - n = min(nFaceDirOption, num); - - //bottom n cards.. - for(i = 0; i < n; i++) - { - cards[num - i - 1].SetFaceUp(false); - } - - for(i = n; i < num; i++) - { - cards[num - i - 1].SetFaceUp(true); - } - - break; - - case CS_FACE_UPDOWN: - - num = cardstack.NumCards(); - n = min(nFaceDirOption, num); - - for(i = 0; i < n; i++) - { - cards[num - i - 1].SetFaceUp(true); - } - - for(i = n; i < num; i++) - { - cards[num - i - 1].SetFaceUp(false); - } - - break; - - case CS_FACE_ANY: //cards can be any orientation - default: - break; - } -} - -bool CardRegion::MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate) -{ - HDC hdc; - - int x, y; - - if(pDestStack == 0) return false; //{ forcedfacedir = -1 ;return 0; } - - if(nNumCards < 0 || nNumCards > cardstack.NumCards()) - return false; - - x = xpos + xoffset * (nNumApparentCards - nNumCards); - y = ypos + yoffset * (nNumApparentCards - nNumCards); - - oldx = x; - oldy = y; - - dragstack = cardstack.Pop(nNumCards); - - //Alter the drag-stack so that it's cards are the same way up - //as the destination. Use the destination's drag-rules - //instead of this ones!! - CardStack temp; - temp.Push(pDestStack->GetCardStack()); - temp.Push(dragstack); - - pDestStack->UpdateFaceDir(temp); - - dragstack = temp.Pop(nNumCards); - - if(fAnimate) - { - iNumDragCards = nNumCards; - PrepareDragBitmaps(nNumCards); - } - - Update(); //Update this stack's size+card count - - if(fAnimate) - { - hdc = GetDC((HWND)parentWnd); - - ZoomCard(hdc, x, y, pDestStack); - - ReleaseDC((HWND)parentWnd, hdc); - ReleaseDragBitmaps(); - } - - // Get a copy of the cardstack - CardStack cs = pDestStack->GetCardStack(); - cs.Push(dragstack); - - pDestStack->SetCardStack(cs); - - //cs = pDestStack->GetCardStack(); - //pDestStack->Update(); - //pDestStack->UpdateFaceDir(cs); - - RedrawIfNotDim(pDestStack, false); - - //forcedfacedir = -1; - return true; -} - -// -// Simple wrappers -// -int CardRegion::NumCards() const -{ - if(fMouseDragging) - return cardstack.NumCards() + dragstack.NumCards(); - else - return cardstack.NumCards(); -} - -bool CardRegion::Lock() -{ - DWORD dw = WaitForSingleObject(mxlock, 0); - - if(dw == WAIT_OBJECT_0) - { - //TRACE("LockStack succeeded\n"); - return true; - } - else - { - //TRACE("LockStack failed\n"); - return false; - } - return false; -} - -bool CardRegion::UnLock() -{ - if(ReleaseMutex(mxlock)) - { - //TRACE("Unlocking stack\n"); - return true; - } - else - { - //TRACE("Unlocking stack failed\n"); - return false; - } -} - -bool CardRegion::PlayCard(CardRegion *pDestStack, int value, int num) -{ - //search the stack for the specified card value... - while(num--) - { - for(int i = 0; i < cardstack.NumCards(); i++) - { - if(cardstack[i].HiVal() == value) - { - //swap the card with one at top pos... - Card card = cardstack.RemoveCard(i); - cardstack.Push(card); - - Redraw(); - - MoveCard(pDestStack, 1, true); - break; - } - } - } - - return true; -} - -// -// Redraw the current stack if it has a different -// layout than the comparison stack. -// -void CardRegion::RedrawIfNotDim(CardRegion *pCompare, bool fFullRedraw) -{ - // - // - // - if( pCompare->xoffset != xoffset || - pCompare->yoffset != yoffset || - pCompare->nThreedCount != nThreedCount || - pCompare->uFaceDirType != uFaceDirType || - pCompare->uFaceDirType != CS_FACE_ANY - ) - { - if(fFullRedraw) - parentWnd.Redraw(); - else - pCompare->Redraw(); - } - -} - -// -// SimulateDrag mimicks the complete drag+drop process. -// It basically just a MoveCard(..), but it calls the -// event callbacks as well. -// -bool CardRegion::SimulateDrag(CardRegion *pDestStack, int iNumDragCards, bool fAnimate) -{ - if(pDestStack == 0) - return false; - - if(CanDragCards(iNumDragCards) != false) - { - //make a list of the cards that would be in the drag list - CardStack tempstack = cardstack.Top(iNumDragCards); - - if(pDestStack->CanDropCards(tempstack)) - { - MoveCard(pDestStack, iNumDragCards, fAnimate); - - if(RemoveCallback) - RemoveCallback(*this, iNumDragCards); - - if(pDestStack->AddCallback) - pDestStack->AddCallback(*pDestStack, pDestStack->cardstack); - - RedrawIfNotDim(pDestStack, true); - } - - } - - return true; -} +// +// CardLib - CardRegion class +// +// Freeware +// Copyright J Brown 2001 +// +#include + +#include "cardlib.h" +#include "cardregion.h" +#include "cardwindow.h" +#include "cardcolor.h" + +HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, int width, int height); + +void PaintRect(HDC hdc, RECT *rect, COLORREF colour); + +CardRegion::CardRegion(CardWindow &parent, int Id, bool visible, int x, int y, int xOffset, int yOffset) +: id(Id), parentWnd(parent), xpos(x), ypos(y), xoffset(xOffset), yoffset(yOffset), fVisible(visible) +{ + width = __cardwidth; + height = __cardheight; + + crBackgnd = RGB(0, 64, 100); + + uFaceDirType = CS_FACE_UP; + nFaceDirOption = 0; + uEmptyImage = CS_EI_SUNK; + + fVisible = visible; + + nThreedCount = 1; + nBackCardIdx = 53; + + Update(); //Update this stack's size+card count + + hdcBackGnd = 0; + hbmBackGnd = 0; + hdcDragCard = 0; + hbmDragCard = 0; + + nDragCardWidth = 0; + nDragCardHeight = 0; + + CanDragCallback = 0; + CanDropCallback = 0; + AddCallback = 0; + RemoveCallback = 0; + ClickCallback = 0; + DblClickCallback = 0; + + uDragRule = CS_DRAG_ALL; + uDropRule = CS_DROP_ALL; + + xjustify = yjustify = xadjust = yadjust = 0; + + nFlashCount = 0; + fFlashVisible = false; + uFlashTimer = (UINT)-1; + + fMouseDragging = false; + + mxlock = CreateMutex(0, FALSE, 0); +} + +CardRegion::~CardRegion() +{ + CloseHandle(mxlock); +} + +void CardRegion::SetBackColor(COLORREF cr) +{ + crBackgnd = cr; +} + +int CardRegion::CalcApparentCards(int realnum) +{ + return ((realnum + nThreedCount - 1) - (realnum + nThreedCount - 1) % nThreedCount) / nThreedCount; +} + +void CardRegion::CalcApparentCards() +{ + nNumApparentCards = CalcApparentCards(cardstack.NumCards()); +} + + +void CardRegion::UpdateSize(void) +{ + if(cardstack.NumCards() > 0) + { + if(xoffset > 0) + width = (nNumApparentCards - 1) * xoffset + __cardwidth; + else + width = (nNumApparentCards - 1) * -xoffset + __cardwidth; + + if(yoffset > 0) + height = (nNumApparentCards - 1) * yoffset + __cardheight; + else + height = (nNumApparentCards - 1) * -yoffset + __cardheight; + } + else + { + width = __cardwidth; + height = __cardheight; + } +} + +CardRegion *CardWindow::CreateRegion(int id, bool fVisible, int x, int y, int xoffset, int yoffset) +{ + CardRegion *cr; + + if(nNumCardRegions == MAXCARDSTACKS) + return FALSE; + + cr = new CardRegion(*this, id, fVisible, x, y, xoffset, yoffset); + cr->SetBackColor(crBackgnd); + cr->SetBackCardIdx(nBackCardIdx); + + Regions[nNumCardRegions++] = cr; + + return cr; +} + +int CardRegion::GetOverlapRatio(int x, int y, int w, int h) +{ + RECT me, him; + RECT inter; + SetRect(&him, x, y, x+w, y+h); + SetRect(&me, xpos, ypos, xpos+width, ypos+height); + + //see if the specified rectangle overlaps us + if(IntersectRect(&inter, &me, &him)) + { + int wi = inter.right - inter.left; + int hi = inter.bottom - inter.top; + + int overlap = wi * hi; + int total = width * height; + + int percent = (overlap << 16) / total; + return (percent * 100) >> 16; + } + //do not overlap + else + { + return 0; + } +} + +bool CardRegion::SetDragRule(UINT uDragType, pCanDragProc proc) +{ + switch(uDragType) + { + case CS_DRAG_NONE: case CS_DRAG_ALL: case CS_DRAG_TOP: + uDragRule = uDragType; + return true; + + case CS_DRAG_CALLBACK: + uDragRule = uDragType; + CanDragCallback = proc; + return true; + + default: + return false; + } +} + +bool CardRegion::SetDropRule(UINT uDropType, pCanDropProc proc) +{ + switch(uDropType) + { + case CS_DROP_NONE: case CS_DROP_ALL: + uDropRule = uDropType; + return true; + + case CS_DROP_CALLBACK: + uDropRule = uDropType; + CanDropCallback = proc; + return true; + + default: + return false; + } +} + +void CardRegion::SetClickProc(pClickProc proc) +{ + ClickCallback = proc; +} + +void CardRegion::SetDblClickProc(pClickProc proc) +{ + DblClickCallback = proc; +} + +void CardRegion::SetAddCardProc(pAddProc proc) +{ + AddCallback = proc; +} + +void CardRegion::SetRemoveCardProc(pRemoveProc proc) +{ + RemoveCallback = proc; +} + +void CardRegion::Update() +{ + CalcApparentCards(); + UpdateSize(); + UpdateFaceDir(cardstack); +} + + +bool CardRegion::SetThreedCount(int count) +{ + if(count < 1) + { + return false; + } + else + { + nThreedCount = count; + return true; + } +} + +void CardRegion::SetOffsets(int x, int y) +{ + xoffset = x; + yoffset = y; +} + +void CardRegion::SetPos(int x, int y) +{ + xpos = x; + ypos = y; +} + +void CardRegion::Show(bool fShow) +{ + fVisible = fShow; +} + +bool CardRegion::IsVisible() +{ + return fVisible; +} + +void CardRegion::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust) +{ + xjustify = xJustify; + yjustify = yJustify; + xadjust = xAdjust; + yadjust = yAdjust; +} + +void CardRegion::SetFaceDirection(UINT uDirType, int nOption) +{ + switch(uDirType) + { + case CS_FACE_UP: case CS_FACE_DOWN: case CS_FACE_DOWNUP: + case CS_FACE_UPDOWN: case CS_FACE_ANY: + uFaceDirType = uDirType; + nFaceDirOption = nOption; + + UpdateFaceDir(cardstack); + + break; + } +} + +UINT CardRegion::GetFaceDirection(int *pnOption) +{ + if(pnOption) + *pnOption = nFaceDirOption; + + return uFaceDirType; +} + +void CardRegion::AdjustPosition(int winwidth, int winheight) +{ + Update(); //Update this stack's card count + size + + switch(xjustify) + { + default: case CS_XJUST_NONE: break; + + case CS_XJUST_CENTER: //centered + xpos = (winwidth - (width & ~0x1)) / 2; + xpos += xadjust; + + if(xoffset < 0) xpos += (width - __cardwidth); + + break; + + case CS_XJUST_RIGHT: //right-aligned + xpos = winwidth - __cardwidth;//width - 20; + xpos += xadjust; + break; + } + + switch(yjustify) + { + default: case CS_YJUST_NONE: break; + + case CS_YJUST_CENTER: //centered + ypos = (winheight - height) / 2; + ypos += yadjust; + if(yoffset < 0) ypos += (height - __cardheight); + break; + + case CS_YJUST_BOTTOM: //bottom-aligned + ypos = winheight - __cardheight;//height - 20; + ypos += yadjust; + break; + } + +} + + +void CardRegion::Flash(int count, int milliseconds) +{ + if(count <= 0) return; + + nFlashCount = count; + fFlashVisible = false; + uFlashTimer = SetTimer((HWND)parentWnd, (WPARAM)this, milliseconds, 0); + + parentWnd.Redraw(); +} + +void CardRegion::StopFlash() +{ + if(uFlashTimer != (UINT)-1) + { + KillTimer((HWND)parentWnd, uFlashTimer); + nFlashCount = 0; + uFlashTimer = (UINT)-1; + fFlashVisible = true; + } +} + +void CardRegion::DoFlash() +{ + if(uFlashTimer != (UINT)-1) + { + fFlashVisible = !fFlashVisible; + + if(--nFlashCount == 0) + { + KillTimer((HWND)parentWnd, uFlashTimer); + uFlashTimer = (UINT)-1; + fFlashVisible = true; + } + + parentWnd.Redraw(); + } +} + +int CardRegion::Id() +{ + return id; +} + +void CardRegion::SetEmptyImage(UINT uImage) +{ + switch(uImage) + { + case CS_EI_NONE: case CS_EI_SUNK: + uEmptyImage = uImage; + break; + + default: + uEmptyImage = CS_EI_NONE; + break; + } + +} + +void CardRegion::SetBackCardIdx(UINT uBackIdx) +{ + if(uBackIdx >= 52 && uBackIdx <= 68) + nBackCardIdx = uBackIdx; +} + +void CardRegion::SetCardStack(const CardStack &cs) +{ + //make a complete copy of the specified stack.. + cardstack = cs; + + // Update the face-direction and stack-size + Update(); +} + +const CardStack & CardRegion::GetCardStack() +{ + //return reference to our internal stack + return cardstack; +} + +// +// Update specified card-stack using THIS stack's +// face direction rules! +// +void CardRegion::UpdateFaceDir(CardStack &cards) +{ + int i, n, num; + + num = cards.NumCards(); + + //Now apply the face direction rules.. + switch(uFaceDirType) + { + case CS_FACE_UP: + + for(i = 0; i < num; i++) + { + cards[i].SetFaceUp(true); + } + + break; + + case CS_FACE_DOWN: + + for(i = 0; i < num; i++) + { + cards[i].SetFaceUp(false); + } + + break; + + case CS_FACE_DOWNUP: + + num = cardstack.NumCards(); + n = min(nFaceDirOption, num); + + //bottom n cards.. + for(i = 0; i < n; i++) + { + cards[num - i - 1].SetFaceUp(false); + } + + for(i = n; i < num; i++) + { + cards[num - i - 1].SetFaceUp(true); + } + + break; + + case CS_FACE_UPDOWN: + + num = cardstack.NumCards(); + n = min(nFaceDirOption, num); + + for(i = 0; i < n; i++) + { + cards[num - i - 1].SetFaceUp(true); + } + + for(i = n; i < num; i++) + { + cards[num - i - 1].SetFaceUp(false); + } + + break; + + case CS_FACE_ANY: //cards can be any orientation + default: + break; + } +} + +bool CardRegion::MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate) +{ + HDC hdc; + + int x, y; + + if(pDestStack == 0) return false; //{ forcedfacedir = -1 ;return 0; } + + if(nNumCards < 0 || nNumCards > cardstack.NumCards()) + return false; + + x = xpos + xoffset * (nNumApparentCards - nNumCards); + y = ypos + yoffset * (nNumApparentCards - nNumCards); + + oldx = x; + oldy = y; + + dragstack = cardstack.Pop(nNumCards); + + //Alter the drag-stack so that it's cards are the same way up + //as the destination. Use the destination's drag-rules + //instead of this ones!! + CardStack temp; + temp.Push(pDestStack->GetCardStack()); + temp.Push(dragstack); + + pDestStack->UpdateFaceDir(temp); + + dragstack = temp.Pop(nNumCards); + + if(fAnimate) + { + iNumDragCards = nNumCards; + PrepareDragBitmaps(nNumCards); + } + + Update(); //Update this stack's size+card count + + if(fAnimate) + { + hdc = GetDC((HWND)parentWnd); + + ZoomCard(hdc, x, y, pDestStack); + + ReleaseDC((HWND)parentWnd, hdc); + ReleaseDragBitmaps(); + } + + // Get a copy of the cardstack + CardStack cs = pDestStack->GetCardStack(); + cs.Push(dragstack); + + pDestStack->SetCardStack(cs); + + //cs = pDestStack->GetCardStack(); + //pDestStack->Update(); + //pDestStack->UpdateFaceDir(cs); + + RedrawIfNotDim(pDestStack, false); + + //forcedfacedir = -1; + return true; +} + +// +// Simple wrappers +// +int CardRegion::NumCards() const +{ + if(fMouseDragging) + return cardstack.NumCards() + dragstack.NumCards(); + else + return cardstack.NumCards(); +} + +bool CardRegion::Lock() +{ + DWORD dw = WaitForSingleObject(mxlock, 0); + + if(dw == WAIT_OBJECT_0) + { + //TRACE("LockStack succeeded\n"); + return true; + } + else + { + //TRACE("LockStack failed\n"); + return false; + } + return false; +} + +bool CardRegion::UnLock() +{ + if(ReleaseMutex(mxlock)) + { + //TRACE("Unlocking stack\n"); + return true; + } + else + { + //TRACE("Unlocking stack failed\n"); + return false; + } +} + +bool CardRegion::PlayCard(CardRegion *pDestStack, int value, int num) +{ + //search the stack for the specified card value... + while(num--) + { + for(int i = 0; i < cardstack.NumCards(); i++) + { + if(cardstack[i].HiVal() == value) + { + //swap the card with one at top pos... + Card card = cardstack.RemoveCard(i); + cardstack.Push(card); + + Redraw(); + + MoveCard(pDestStack, 1, true); + break; + } + } + } + + return true; +} + +// +// Redraw the current stack if it has a different +// layout than the comparison stack. +// +void CardRegion::RedrawIfNotDim(CardRegion *pCompare, bool fFullRedraw) +{ + // + // + // + if( pCompare->xoffset != xoffset || + pCompare->yoffset != yoffset || + pCompare->nThreedCount != nThreedCount || + pCompare->uFaceDirType != uFaceDirType || + pCompare->uFaceDirType != CS_FACE_ANY + ) + { + if(fFullRedraw) + parentWnd.Redraw(); + else + pCompare->Redraw(); + } + +} + +// +// SimulateDrag mimicks the complete drag+drop process. +// It basically just a MoveCard(..), but it calls the +// event callbacks as well. +// +bool CardRegion::SimulateDrag(CardRegion *pDestStack, int iNumDragCards, bool fAnimate) +{ + if(pDestStack == 0) + return false; + + if(CanDragCards(iNumDragCards) != false) + { + //make a list of the cards that would be in the drag list + CardStack tempstack = cardstack.Top(iNumDragCards); + + if(pDestStack->CanDropCards(tempstack)) + { + MoveCard(pDestStack, iNumDragCards, fAnimate); + + if(RemoveCallback) + RemoveCallback(*this, iNumDragCards); + + if(pDestStack->AddCallback) + pDestStack->AddCallback(*pDestStack, pDestStack->cardstack); + + RedrawIfNotDim(pDestStack, true); + } + + } + + return true; +} diff --git a/rosapps/games/solitaire/cardlib/cardregion.h b/rosapps/games/solitaire/cardlib/cardregion.h index 1dc9498492f..d3b4179c9f0 100644 --- a/rosapps/games/solitaire/cardlib/cardregion.h +++ b/rosapps/games/solitaire/cardlib/cardregion.h @@ -1,216 +1,216 @@ -#ifndef CARDREGION_INCLUDED -#define CARDREGION_INCLUDED - -#include "globals.h" -#include "cardstack.h" -#include "cardlib.h" - -class CardWindow; - -// -// This class defines a physical card-stack, -// which draws the cards, supports -// - -class CardRegion -{ - friend class CardWindow; - friend class CardStack; - - // - // Constructor is PRIVATE - only - // a CardWindow can create cardstacks! - // - CardRegion(CardWindow &parent, int id, bool fVisible, - int x, int y, int xOffset, int yOffset); - - ~CardRegion(); - -public: - - void SetBackColor(COLORREF cr); - - void SetCardStack(const CardStack &cs); - const CardStack & GetCardStack(); - - // - // Event-callback support - // - bool SetDragRule(UINT uDragType, pCanDragProc proc = 0); - bool SetDropRule(UINT uDropType, pCanDropProc proc = 0); - - void SetClickProc (pClickProc proc); - void SetDblClickProc (pClickProc proc); - - void SetAddCardProc (pAddProc proc); - void SetRemoveCardProc (pRemoveProc proc); - - // - // Physical attribute support - // - bool SetThreedCount (int count); - void SetOffsets (int x, int y); - void SetPos (int x, int y); - void Show (bool fShow); - bool IsVisible (); - - void SetEmptyImage (UINT uImage); - void SetBackCardIdx (UINT uBackIdx); - void SetPlacement (UINT xJustify, UINT yJustify, int xAdjust, int yAdjust); - - void Update(); - void Redraw(); - - void SetFaceDirection(UINT uDirType, int nOption); - UINT GetFaceDirection(int *pnOption); - - void Flash(int count, int timeout); - void StopFlash(); - - int Id(); - - CardWindow &GetCardWindow() { return parentWnd; } - - bool PlayCard(CardRegion *pDestStack, int value, int num); - bool MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate); - bool SimulateDrag(CardRegion *pDestStack, int nNumCards, bool fAnimate); - - bool Lock(); - bool UnLock(); - - // - // Common wrappers for the CardStack object - // - int NumCards() const; - void NewDeck() { cardstack.NewDeck(); } - void Shuffle() { cardstack.Shuffle(); } - void Clear() { cardstack.Clear(); } - - void Reverse() { cardstack.Reverse(); } - - void Push(const Card card) { cardstack.Push(card); } - void Push(const CardStack &cs) { cardstack.Push(cs); } - - Card Pop() { return cardstack.Pop(); } - CardStack Pop(int items) { return cardstack.Pop(items); } - - Card Top() { return cardstack.Top(); } - CardStack Top(int items) { return cardstack.Top(items); } - - -private: - - void DoFlash(); - void RedrawIfNotDim(CardRegion *compare, bool fFullRedraw); - - void UpdateFaceDir(CardStack &cards); - void Clip(HDC hdc); - void Render(HDC hdc); - int GetOverlapRatio(int x, int y, int width, int height); - - void MoveDragCardTo(HDC hdc, int x, int y); - void ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *dest); - - void RenderBottomMost(HDC hdc, int minustopmost = 0); - void PrepareDragBitmaps(int numtodrag); - void PrepareDragBitmapsThreed(int numtodrag); - void ReleaseDragBitmaps(void); - - bool CanDragCards(int iNumCards); - bool CanDropCards(CardStack &cards); - - void CalcApparentCards(); - int CalcApparentCards(int realnum); - - void UpdateSize(); - void AdjustPosition(int winwidth, int winheight); - - bool IsPointInStack(int x, int y); - - int GetNumDragCards(int x, int y); - bool OnLButtonDown(int x, int y); - bool OnLButtonDblClk(int x, int y); - bool OnMouseMove(int x, int y); - bool OnLButtonUp(int x, int y); - - - // - // Private data members - // - - int id; - - CardWindow &parentWnd; - - CardStack cardstack; //cards in this stack - CardStack dragstack; //cards which we might be dragging - - bool fMouseDragging; - - int xpos; //coordinates of stack - int ypos; - - int xoffset; //direction that cards take - int yoffset; - - int width; //stack-size of all cards - int height; - - // - // justify / placement vars - int xjustify; - int yjustify; - int xadjust; - int yadjust; - - // - // Used for mouse-dragging / moving cards - // - int iNumDragCards; - int mousexoffset; - int mouseyoffset; - int oldx; - int oldy; - - int nDragCardWidth; - int nDragCardHeight; - - HDC hdcBackGnd; - HBITMAP hbmBackGnd; - HDC hdcDragCard; - HBITMAP hbmDragCard; - - int nNumApparentCards; - int nThreedCount; - bool fVisible; - - int nFlashCount; - bool fFlashVisible; - UINT uFlashTimer; - - COLORREF crBackgnd; - - UINT uEmptyImage; - UINT uFaceDirType; - int nFaceDirOption; - int nBackCardIdx; - - UINT uDragRule; - UINT uDropRule; - - // - // Stack callback support - // - pCanDragProc CanDragCallback; - pCanDropProc CanDropCallback; - pClickProc ClickCallback; - pClickProc DblClickCallback; - pAddProc AddCallback; - pRemoveProc RemoveCallback; - - //locking mechanism to prevent user dragging etc - HANDLE mxlock; -}; - -#endif - +#ifndef CARDREGION_INCLUDED +#define CARDREGION_INCLUDED + +#include "globals.h" +#include "cardstack.h" +#include "cardlib.h" + +class CardWindow; + +// +// This class defines a physical card-stack, +// which draws the cards, supports +// + +class CardRegion +{ + friend class CardWindow; + friend class CardStack; + + // + // Constructor is PRIVATE - only + // a CardWindow can create cardstacks! + // + CardRegion(CardWindow &parent, int id, bool fVisible, + int x, int y, int xOffset, int yOffset); + + ~CardRegion(); + +public: + + void SetBackColor(COLORREF cr); + + void SetCardStack(const CardStack &cs); + const CardStack & GetCardStack(); + + // + // Event-callback support + // + bool SetDragRule(UINT uDragType, pCanDragProc proc = 0); + bool SetDropRule(UINT uDropType, pCanDropProc proc = 0); + + void SetClickProc (pClickProc proc); + void SetDblClickProc (pClickProc proc); + + void SetAddCardProc (pAddProc proc); + void SetRemoveCardProc (pRemoveProc proc); + + // + // Physical attribute support + // + bool SetThreedCount (int count); + void SetOffsets (int x, int y); + void SetPos (int x, int y); + void Show (bool fShow); + bool IsVisible (); + + void SetEmptyImage (UINT uImage); + void SetBackCardIdx (UINT uBackIdx); + void SetPlacement (UINT xJustify, UINT yJustify, int xAdjust, int yAdjust); + + void Update(); + void Redraw(); + + void SetFaceDirection(UINT uDirType, int nOption); + UINT GetFaceDirection(int *pnOption); + + void Flash(int count, int timeout); + void StopFlash(); + + int Id(); + + CardWindow &GetCardWindow() { return parentWnd; } + + bool PlayCard(CardRegion *pDestStack, int value, int num); + bool MoveCard(CardRegion *pDestStack, int nNumCards, bool fAnimate); + bool SimulateDrag(CardRegion *pDestStack, int nNumCards, bool fAnimate); + + bool Lock(); + bool UnLock(); + + // + // Common wrappers for the CardStack object + // + int NumCards() const; + void NewDeck() { cardstack.NewDeck(); } + void Shuffle() { cardstack.Shuffle(); } + void Clear() { cardstack.Clear(); } + + void Reverse() { cardstack.Reverse(); } + + void Push(const Card card) { cardstack.Push(card); } + void Push(const CardStack &cs) { cardstack.Push(cs); } + + Card Pop() { return cardstack.Pop(); } + CardStack Pop(int items) { return cardstack.Pop(items); } + + Card Top() { return cardstack.Top(); } + CardStack Top(int items) { return cardstack.Top(items); } + + +private: + + void DoFlash(); + void RedrawIfNotDim(CardRegion *compare, bool fFullRedraw); + + void UpdateFaceDir(CardStack &cards); + void Clip(HDC hdc); + void Render(HDC hdc); + int GetOverlapRatio(int x, int y, int width, int height); + + void MoveDragCardTo(HDC hdc, int x, int y); + void ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *dest); + + void RenderBottomMost(HDC hdc, int minustopmost = 0); + void PrepareDragBitmaps(int numtodrag); + void PrepareDragBitmapsThreed(int numtodrag); + void ReleaseDragBitmaps(void); + + bool CanDragCards(int iNumCards); + bool CanDropCards(CardStack &cards); + + void CalcApparentCards(); + int CalcApparentCards(int realnum); + + void UpdateSize(); + void AdjustPosition(int winwidth, int winheight); + + bool IsPointInStack(int x, int y); + + int GetNumDragCards(int x, int y); + bool OnLButtonDown(int x, int y); + bool OnLButtonDblClk(int x, int y); + bool OnMouseMove(int x, int y); + bool OnLButtonUp(int x, int y); + + + // + // Private data members + // + + int id; + + CardWindow &parentWnd; + + CardStack cardstack; //cards in this stack + CardStack dragstack; //cards which we might be dragging + + bool fMouseDragging; + + int xpos; //coordinates of stack + int ypos; + + int xoffset; //direction that cards take + int yoffset; + + int width; //stack-size of all cards + int height; + + // + // justify / placement vars + int xjustify; + int yjustify; + int xadjust; + int yadjust; + + // + // Used for mouse-dragging / moving cards + // + int iNumDragCards; + int mousexoffset; + int mouseyoffset; + int oldx; + int oldy; + + int nDragCardWidth; + int nDragCardHeight; + + HDC hdcBackGnd; + HBITMAP hbmBackGnd; + HDC hdcDragCard; + HBITMAP hbmDragCard; + + int nNumApparentCards; + int nThreedCount; + bool fVisible; + + int nFlashCount; + bool fFlashVisible; + UINT uFlashTimer; + + COLORREF crBackgnd; + + UINT uEmptyImage; + UINT uFaceDirType; + int nFaceDirOption; + int nBackCardIdx; + + UINT uDragRule; + UINT uDropRule; + + // + // Stack callback support + // + pCanDragProc CanDragCallback; + pCanDropProc CanDropCallback; + pClickProc ClickCallback; + pClickProc DblClickCallback; + pAddProc AddCallback; + pRemoveProc RemoveCallback; + + //locking mechanism to prevent user dragging etc + HANDLE mxlock; +}; + +#endif + diff --git a/rosapps/games/solitaire/cardlib/cardrgndraw.cpp b/rosapps/games/solitaire/cardlib/cardrgndraw.cpp index a5da84d8921..2f20010695b 100644 --- a/rosapps/games/solitaire/cardlib/cardrgndraw.cpp +++ b/rosapps/games/solitaire/cardlib/cardrgndraw.cpp @@ -1,613 +1,613 @@ -// -// CardLib - CardRegion drawing support -// -// Freeware -// Copyright J Brown 2001 -// -#include -#include "cardlib.h" -#include "cardregion.h" -#include "cardcolor.h" - -HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette); -void PaintRect(HDC hdc, RECT *rect, COLORREF colour); -void CardBlt(HDC hdc, int x, int y, int nCardNum); -void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height); - -// -// Draw specified card at position x, y -// xoff - source offset from left of card -// yoff - source offset from top of card -// width - width to draw -// height - height to draw -// -void CardBlt(HDC hdc, int x, int y, int nCardNum)//, int xoff, int yoff, int width, int height) -{ - int sx = nCardNum * __cardwidth; - int sy = 0; - int width = __cardwidth; - int height = __cardheight; - - //draw main center band - BitBlt(hdc, x+2, y, width - 4, height, __hdcCardBitmaps, sx+2, sy+0, SRCCOPY); - - //draw the two bits to the left - BitBlt(hdc, x, y+2, 1, height - 4, __hdcCardBitmaps, sx+0, sy+2, SRCCOPY); - BitBlt(hdc, x+1, y+1, 1, height - 2, __hdcCardBitmaps, sx+1, sy+1, SRCCOPY); - - //draw the two bits to the right - BitBlt(hdc, x+width-2, y+1, 1, height - 2, __hdcCardBitmaps, sx+width-2, sy+1, SRCCOPY); - BitBlt(hdc, x+width-1, y+2, 1, height - 4, __hdcCardBitmaps, sx+width-1, sy+2, SRCCOPY); -} - -// -// Draw a shape this this: -// -// ++++++++++++ -// ++++++++++++++ -// ++ ++ -// -void DrawHorzCardStrip(HDC hdc, int x, int y, int nCardNum, int height, BOOL fDrawTips) -{ - int sx = nCardNum * __cardwidth; - int sy = 0; - int one = 1; - int two = 2; - BOOL tips = fDrawTips ? FALSE : TRUE; - - if(height == 0) return; - - if(height < 0) - { - sy = sy + __cardheight; - y -= height; - one = -one; - two = -two; - } - - // draw the main vertical band - // - BitBlt(hdc, x + 2, y, __cardwidth - 4, height, __hdcCardBitmaps, sx+2, sy, SRCCOPY); - - //if(height <= 1) return; - - // draw the "lips" at the left and right - BitBlt(hdc, x+1, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+1, sy+one, SRCCOPY); - BitBlt(hdc, x+__cardwidth-2, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+__cardwidth-2, sy+one, SRCCOPY); - - //if(height <= 2) return; - - // draw the outer-most lips - BitBlt(hdc, x, y+two, 1, height-two*tips, __hdcCardBitmaps, sx, sy+two, SRCCOPY); - BitBlt(hdc, x+__cardwidth-1, y+two, 1, height-two*tips, __hdcCardBitmaps, sx+__cardwidth-1, sy+two, SRCCOPY); -} - -// -// Draw a shape like this: -// -// +++ -// +++ -// +++ -// +++ -// +++ -// +++ -// +++ -// +++ -// +++ -// +++ -// -// -void DrawVertCardStrip(HDC hdc, int x, int y, int nCardNum, int width, BOOL fDrawTips) -{ - int sx = nCardNum * __cardwidth; - int sy = 0; - int one = 1; - int two = 2; - BOOL tips = fDrawTips ? FALSE : TRUE; - - if(width == 0) return; - - - if(width < 0) - { - sx = sx + __cardwidth; - x -= width; - one = -1; - two = -2; - } - - // draw the main vertical band - // - BitBlt(hdc, x, y + 2, width, __cardheight - 4, __hdcCardBitmaps, sx, sy+2, SRCCOPY); - - //if(width <= 1) return; - - // draw the "lips" at the top and bottom - BitBlt(hdc, x+one, y+1, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + 1, SRCCOPY); - BitBlt(hdc, x+one, y+__cardheight-2, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + __cardheight-2, SRCCOPY); - - //if(width <= 2) return; - - // draw the outer-most lips - BitBlt(hdc, x+two, y, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy, SRCCOPY); - BitBlt(hdc, x+two, y+__cardheight-1, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy + __cardheight-1, SRCCOPY); -} - -// -// xdir - <0 or >0 -// ydir - <0 or >0 -// -void DrawCardCorner(HDC hdc, int x, int y, int cardval, int xdir, int ydir) -{ - int sx = cardval * __cardwidth; - int sy = 0; - - HDC hdcSource = __hdcCardBitmaps; - - if(xdir < 0) - { - x += __cardwidth + xdir - 1; - sx += __cardwidth + xdir - 1; - } - else - { - x += xdir; - sx += xdir; - } - - if(ydir < 0) - { - y += __cardheight + ydir - 1; - sy += __cardheight + ydir - 1; - } - else - { - y += ydir; - sy += ydir; - } - - //convert x,y directions to -1, +1 - xdir = xdir < 0 ? -1 : 1; - ydir = ydir < 0 ? -1 : 1; - - SetPixel(hdc, x+xdir, y , GetPixel(hdcSource, sx+xdir, sy)); - SetPixel(hdc, x, y, GetPixel(hdcSource, sx, sy)); - SetPixel(hdc, x, y+ydir, GetPixel(hdcSource, sx, sy+ydir)); - -} - -// -// Draw a card (i.e. miss out the corners) -// -void DrawCard(HDC hdc, int x, int y, HDC hdcDragCard, int width, int height) -{ - //draw main center band - BitBlt(hdc, x+2, y, width - 4, height, hdcDragCard, 2, 0, SRCCOPY); - - //draw the two bits to the left - BitBlt(hdc, x, y+2, 1, height - 4, hdcDragCard, 0, 2, SRCCOPY); - BitBlt(hdc, x+1, y+1, 1, height - 2, hdcDragCard, 1, 1, SRCCOPY); - - //draw the two bits to the right - BitBlt(hdc, x+width-2, y+1, 1, height - 2, hdcDragCard, width-2, 1, SRCCOPY); - BitBlt(hdc, x+width-1, y+2, 1, height - 4, hdcDragCard, width-1, 2, SRCCOPY); -} - -// -// Clip a card SHAPE - basically any rectangle -// with rounded corners -// -int ClipCard(HDC hdc, int x, int y, int width, int height) -{ - ExcludeClipRect(hdc, x+2, y, x+2+width-4, y+ height); - ExcludeClipRect(hdc, x, y+2, x+1, y+2+height-4); - ExcludeClipRect(hdc, x+1, y+1, x+2, y+1+height-2); - ExcludeClipRect(hdc, x+width-2, y+1, x+width-2+1, y+1+height-2); - ExcludeClipRect(hdc, x+width-1, y+2, x+width-1+1, y+2+height-4); - return 0; -} - -void CardRegion::Clip(HDC hdc) -{ - int numtoclip; - - if(fVisible == false) - return; - - Update(); //Update this stack's size+card count - numtoclip = nNumApparentCards; - - //if we are making this stack flash on/off, then only - //clip the stack for drawing if the flash is in its ON state - if(nFlashCount != 0) - { - if(fFlashVisible == FALSE) - numtoclip = 0; - } - - //if offset along a diagonal - if(xoffset != 0 && yoffset != 0 && cardstack.NumCards() != 0) - { - for(int j = 0; j < numtoclip; j ++) - { - ClipCard(hdc, xpos + xoffset * j, ypos + yoffset * j, __cardwidth, __cardheight); - } - } - //otherwise if just offset along a horizontal/vertical axis - else - { - if(yoffset < 0 && numtoclip > 0) - { - ClipCard(hdc, xpos, ypos-((numtoclip-1)*-yoffset), width, height); - } - else if(xoffset < 0 && numtoclip > 0) - { - ClipCard(hdc, xpos-((numtoclip-1)*-xoffset), ypos, width, height); - } - else - { - ClipCard(hdc, xpos, ypos, width, height); - } - } - -} - -void CardRegion::Render(HDC hdc) -{ - int cardnum = 0; - int numtodraw; - BOOL fDrawTips; - - Update(); //Update this stack's card count + size - - numtodraw = nNumApparentCards; - - if(nFlashCount != 0) - { - if(fFlashVisible == false) - numtodraw = 0; - } - - if(fVisible == 0) return; - - cardnum = cardstack.NumCards() - numtodraw; - int counter; - - for(counter = 0; counter < numtodraw; counter++) - { - int cardval; - - int x = xoffset * counter + xpos; - int y = yoffset * counter + ypos; - - //if about to draw last card, then actually draw the top card - if(counter == numtodraw - 1) cardnum = cardstack.NumCards() - 1; - - Card card = cardstack.cardlist[cardnum]; - cardval = card.Idx(); - - if(card.FaceDown()) - cardval = nBackCardIdx; //card-back - - //only draw the visible part of the card - if(counter < numtodraw - 1) - { - if(yoffset != 0 && xoffset != 0) - fDrawTips = FALSE; - else - fDrawTips = TRUE; - - if(yoffset != 0 && abs(xoffset) == 1 || xoffset != 0 && abs(yoffset) == 1) - fDrawTips = TRUE; - - //draw horizontal strips - if(yoffset > 0) - { - DrawHorzCardStrip(hdc, x, y, cardval, yoffset, fDrawTips); - } - else if(yoffset < 0) - { - DrawHorzCardStrip(hdc, x, y+__cardheight+yoffset, cardval, yoffset, fDrawTips); - } - - //draw some vertical bars - if(xoffset > 0) - { - DrawVertCardStrip(hdc, x, y, cardval, xoffset, fDrawTips); - } - else if(xoffset < 0) - { - DrawVertCardStrip(hdc, x+__cardwidth+xoffset, y, cardval, xoffset, fDrawTips); - } - - if(yoffset != 0 && xoffset != 0)//fDrawTips == FALSE) - { - //if we didn't draw any tips, then this is a 2-dim stack - //(i.e, it goes at a diagonal). - //in this case, we need to fill in the small triangle in - //each corner! - DrawCardCorner(hdc, x, y, cardval, xoffset, yoffset); - } - } - //if the top card, draw the whole thing - else - { - CardBlt(hdc, x, y, cardval); - } - - cardnum ++; - - } //end of index - - if(counter == 0) //if the cardstack is empty, then draw it that way - { - int x = xpos; - int y = ypos; - - switch(uEmptyImage) - { - default: case CS_EI_NONE: - //this wipes the RECT variable, so watch out! - //SetRect(&rect, x, y, x+__cardwidth, y+__cardheight); - //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd)); - parentWnd.PaintCardRgn(hdc, x, y, __cardwidth, __cardheight, x, y); - break; - - case CS_EI_SUNK: //case CS_EI_CIRC: case CS_EI_X: - DrawCard(hdc, x, y, __hdcPlaceHolder, __cardwidth, __cardheight); - break; - } - - } - - return; -} - -int calc_offset(int offset, int numcards, int numtodrag, int realvisible) -{ - if(offset >= 0) - return -offset * numcards; - else - return -offset * (numtodrag) + - -offset * (realvisible - 1); -} - -void CardRegion::PrepareDragBitmaps(int numtodrag) -{ - RECT rect; - HDC hdc; - int icard; - int numcards = cardstack.NumCards(); - int xoff, yoff; - - if(nThreedCount > 1) - { - PrepareDragBitmapsThreed(numtodrag); - return; - } - - //work out how big the bitmaps need to be - nDragCardWidth = (numtodrag - 1) * abs(xoffset) + __cardwidth; - nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight; - - //Create bitmap for the back-buffer - hdc = GetDC(NULL); - hdcBackGnd = CreateCompatibleDC(hdc); - hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight); - SelectObject(hdcBackGnd, hbmBackGnd); - - //Create bitmap for the drag-image - hdcDragCard = CreateCompatibleDC(hdc); - hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight); - SelectObject(hdcDragCard, hbmDragCard); - ReleaseDC(NULL, hdc); - - UseNicePalette(hdcBackGnd, __hPalette); - UseNicePalette(hdcDragCard, __hPalette); - - int realvisible = numcards / nThreedCount; - - //if(numcards > 0 && realvisible == 0) realvisible = 1; - int iwhichcard = numcards - 1; - if(nThreedCount == 1) iwhichcard = 0; - - //grab the first bit of background so we can prep the back buffer; do this by - //rendering the card stack (minus the card we are dragging) to the temporary - //background buffer, so it appears if we have lifted the card from the stack - //PaintRect(hdcBackGnd, &rect, crBackgnd); - SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight); - - xoff = calc_offset(xoffset, numcards, numtodrag, realvisible); - yoff = calc_offset(yoffset, numcards, numtodrag, realvisible); - - parentWnd.PaintCardRgn(hdcBackGnd, 0, 0, nDragCardWidth, nDragCardHeight, xpos - xoff, ypos - yoff); - - // - // Render the cardstack into the back-buffer. The stack - // has already had the dragcards removed, so just draw - // what is left - // - for(icard = 0; icard < realvisible; icard++) - { - Card card = cardstack.cardlist[iwhichcard]; - int nCardVal; - - nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx; - - xoff = xoffset * icard + calc_offset(xoffset, numcards, numtodrag, realvisible);//- xoffset * ((numcards+numtodrag) / nThreedCount - numtodrag); - yoff = yoffset * icard + calc_offset(yoffset, numcards, numtodrag, realvisible);//- yoffset * ((numcards+numtodrag) / nThreedCount - numtodrag); - - CardBlt(hdcBackGnd, xoff, yoff, nCardVal); - iwhichcard++; - } - - // - // If there are no cards under this one, just draw the place holder - // - if(numcards == 0) - { - int xoff = 0, yoff = 0; - - if(xoffset < 0) xoff = nDragCardWidth - __cardwidth; - if(yoffset < 0) yoff = nDragCardHeight - __cardheight; - - switch(uEmptyImage) - { - case CS_EI_NONE: - //No need to draw anything: We already cleared the - //back-buffer before the main loop.. - - //SetRect(&rc, xoff, yoff, xoff+ __cardwidth, yoff + __cardheight); - //PaintRect(hdcBackGnd, &rc, MAKE_PALETTERGB(crBackgnd)); - //parentWnd.PaintCardRgn(hdcBackGnd, xoff, yoff, __cardwidth, __cardheight, xpos, ypos);// + xoff, ypos + yoff); - break; - - case CS_EI_SUNK: - DrawCard(hdcBackGnd, xoff, yoff, __hdcPlaceHolder, __cardwidth, __cardheight); - break; - } - } - - // - // now render the drag-cards into the dragcard image - // - PaintRect(hdcDragCard, &rect, crBackgnd); - - for(icard = 0; icard < numtodrag; icard++) - { - int nCardVal; - - if(xoffset >= 0) xoff = xoffset * icard; - else xoff = -xoffset * (numtodrag - icard - 1); - - if(yoffset >= 0) yoff = yoffset * icard; - else yoff = -yoffset * (numtodrag - icard - 1); - - Card card = dragstack.cardlist[icard]; - - nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx; - - CardBlt(hdcDragCard, xoff, yoff, nCardVal); - } -} - -void CardRegion::PrepareDragBitmapsThreed(int numtodrag) -{ - RECT rect; - HDC hdc; - int icard; - int numunder = 0; - int iwhichcard; - - int numcards = cardstack.NumCards(); - - //work out how big the bitmaps need to be - nDragCardWidth = (numtodrag - 1) * abs(xoffset) + __cardwidth; - nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight; - - //Create bitmap for the back-buffer - hdc = GetDC(NULL); - hdcBackGnd = CreateCompatibleDC(hdc); - hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight); - SelectObject(hdcBackGnd, hbmBackGnd); - - //create bitmap for the drag-image - hdcDragCard = CreateCompatibleDC(hdc); - hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight); - SelectObject(hdcDragCard, hbmDragCard); - ReleaseDC(NULL, hdc); - - UseNicePalette(hdcBackGnd, __hPalette); - UseNicePalette(hdcDragCard, __hPalette); - - //grab the first bit of background so we can prep the back buffer; do this by - //rendering the card stack (minus the card we are dragging) to the temporary - //background buffer, so it appears if we have lifted the card from the stack - //--SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight); - //--PaintRect(hdcBackGnd, &rect, crBackgnd); - - int threedadjust = numcards % nThreedCount == 0; - - numunder = CalcApparentCards(numcards); - iwhichcard = (numcards+numtodrag) - numunder - 1; - if(nThreedCount == 1) iwhichcard = 0; - - int xoff = calc_offset(xoffset, numunder, numtodrag, numunder); - int yoff = calc_offset(yoffset, numunder, numtodrag, numunder); - - parentWnd.PaintCardRgn(hdcBackGnd, 0,0, nDragCardWidth,nDragCardHeight, xpos - xoff,ypos - yoff); - - // - // Render the cardstack into the back-buffer. The stack - // has already had the dragcards removed, so just draw - // what is left - // - for(icard = 0; icard < numunder; icard++) - { - Card card = cardstack.cardlist[iwhichcard]; - int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx; - - CardBlt(hdcBackGnd, - xoffset * icard - xoffset*(numunder-numtodrag+threedadjust), - yoffset * icard - yoffset*(numunder-numtodrag+threedadjust), - nCardVal); - - iwhichcard++; - } - - // - // If there are no cards under this one, just draw the place holder - // - if(numcards == 0) - { - switch(uEmptyImage) - { - case CS_EI_NONE: - //no need! we've already cleared the whole - //back-buffer before the main loop! - //SetRect(&rect, 0, 0, __cardwidth, __cardheight); - //PaintRect(hdcBackGnd, &rect, MAKE_PALETTERGB(crBackgnd)); - break; - - case CS_EI_SUNK: - DrawCard(hdcBackGnd, 0, 0, __hdcPlaceHolder, __cardwidth, __cardheight); - break; - - } - } - - // - // now render the drag-cards into the dragcard image - // - PaintRect(hdcDragCard, &rect, crBackgnd); - - for(icard = 0; icard < numtodrag; icard++) - { - Card card = dragstack.cardlist[icard]; - int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx; - - CardBlt(hdcDragCard, xoffset * icard, yoffset * icard, nCardVal); - } -} - -void CardRegion::ReleaseDragBitmaps(void) -{ - //SelectObject(hdcBackGnd, hOld1); - DeleteObject(hbmBackGnd); - DeleteDC(hdcBackGnd); - - //SelectObject(hdcDragCard, hOld2); - DeleteObject(hbmDragCard); - DeleteDC(hdcDragCard); -} - - -void CardRegion::Redraw() -{ - HDC hdc = GetDC((HWND)parentWnd); - - Update(); - Render(hdc); - - ReleaseDC((HWND)parentWnd, hdc); -} +// +// CardLib - CardRegion drawing support +// +// Freeware +// Copyright J Brown 2001 +// +#include +#include "cardlib.h" +#include "cardregion.h" +#include "cardcolor.h" + +HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette); +void PaintRect(HDC hdc, RECT *rect, COLORREF colour); +void CardBlt(HDC hdc, int x, int y, int nCardNum); +void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height); + +// +// Draw specified card at position x, y +// xoff - source offset from left of card +// yoff - source offset from top of card +// width - width to draw +// height - height to draw +// +void CardBlt(HDC hdc, int x, int y, int nCardNum)//, int xoff, int yoff, int width, int height) +{ + int sx = nCardNum * __cardwidth; + int sy = 0; + int width = __cardwidth; + int height = __cardheight; + + //draw main center band + BitBlt(hdc, x+2, y, width - 4, height, __hdcCardBitmaps, sx+2, sy+0, SRCCOPY); + + //draw the two bits to the left + BitBlt(hdc, x, y+2, 1, height - 4, __hdcCardBitmaps, sx+0, sy+2, SRCCOPY); + BitBlt(hdc, x+1, y+1, 1, height - 2, __hdcCardBitmaps, sx+1, sy+1, SRCCOPY); + + //draw the two bits to the right + BitBlt(hdc, x+width-2, y+1, 1, height - 2, __hdcCardBitmaps, sx+width-2, sy+1, SRCCOPY); + BitBlt(hdc, x+width-1, y+2, 1, height - 4, __hdcCardBitmaps, sx+width-1, sy+2, SRCCOPY); +} + +// +// Draw a shape this this: +// +// ++++++++++++ +// ++++++++++++++ +// ++ ++ +// +void DrawHorzCardStrip(HDC hdc, int x, int y, int nCardNum, int height, BOOL fDrawTips) +{ + int sx = nCardNum * __cardwidth; + int sy = 0; + int one = 1; + int two = 2; + BOOL tips = fDrawTips ? FALSE : TRUE; + + if(height == 0) return; + + if(height < 0) + { + sy = sy + __cardheight; + y -= height; + one = -one; + two = -two; + } + + // draw the main vertical band + // + BitBlt(hdc, x + 2, y, __cardwidth - 4, height, __hdcCardBitmaps, sx+2, sy, SRCCOPY); + + //if(height <= 1) return; + + // draw the "lips" at the left and right + BitBlt(hdc, x+1, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+1, sy+one, SRCCOPY); + BitBlt(hdc, x+__cardwidth-2, y+one, 1, height-one*tips, __hdcCardBitmaps, sx+__cardwidth-2, sy+one, SRCCOPY); + + //if(height <= 2) return; + + // draw the outer-most lips + BitBlt(hdc, x, y+two, 1, height-two*tips, __hdcCardBitmaps, sx, sy+two, SRCCOPY); + BitBlt(hdc, x+__cardwidth-1, y+two, 1, height-two*tips, __hdcCardBitmaps, sx+__cardwidth-1, sy+two, SRCCOPY); +} + +// +// Draw a shape like this: +// +// +++ +// +++ +// +++ +// +++ +// +++ +// +++ +// +++ +// +++ +// +++ +// +++ +// +// +void DrawVertCardStrip(HDC hdc, int x, int y, int nCardNum, int width, BOOL fDrawTips) +{ + int sx = nCardNum * __cardwidth; + int sy = 0; + int one = 1; + int two = 2; + BOOL tips = fDrawTips ? FALSE : TRUE; + + if(width == 0) return; + + + if(width < 0) + { + sx = sx + __cardwidth; + x -= width; + one = -1; + two = -2; + } + + // draw the main vertical band + // + BitBlt(hdc, x, y + 2, width, __cardheight - 4, __hdcCardBitmaps, sx, sy+2, SRCCOPY); + + //if(width <= 1) return; + + // draw the "lips" at the top and bottom + BitBlt(hdc, x+one, y+1, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + 1, SRCCOPY); + BitBlt(hdc, x+one, y+__cardheight-2, width-one*tips, 1, __hdcCardBitmaps, sx+one, sy + __cardheight-2, SRCCOPY); + + //if(width <= 2) return; + + // draw the outer-most lips + BitBlt(hdc, x+two, y, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy, SRCCOPY); + BitBlt(hdc, x+two, y+__cardheight-1, width-two*tips, 1, __hdcCardBitmaps, sx+two, sy + __cardheight-1, SRCCOPY); +} + +// +// xdir - <0 or >0 +// ydir - <0 or >0 +// +void DrawCardCorner(HDC hdc, int x, int y, int cardval, int xdir, int ydir) +{ + int sx = cardval * __cardwidth; + int sy = 0; + + HDC hdcSource = __hdcCardBitmaps; + + if(xdir < 0) + { + x += __cardwidth + xdir - 1; + sx += __cardwidth + xdir - 1; + } + else + { + x += xdir; + sx += xdir; + } + + if(ydir < 0) + { + y += __cardheight + ydir - 1; + sy += __cardheight + ydir - 1; + } + else + { + y += ydir; + sy += ydir; + } + + //convert x,y directions to -1, +1 + xdir = xdir < 0 ? -1 : 1; + ydir = ydir < 0 ? -1 : 1; + + SetPixel(hdc, x+xdir, y , GetPixel(hdcSource, sx+xdir, sy)); + SetPixel(hdc, x, y, GetPixel(hdcSource, sx, sy)); + SetPixel(hdc, x, y+ydir, GetPixel(hdcSource, sx, sy+ydir)); + +} + +// +// Draw a card (i.e. miss out the corners) +// +void DrawCard(HDC hdc, int x, int y, HDC hdcDragCard, int width, int height) +{ + //draw main center band + BitBlt(hdc, x+2, y, width - 4, height, hdcDragCard, 2, 0, SRCCOPY); + + //draw the two bits to the left + BitBlt(hdc, x, y+2, 1, height - 4, hdcDragCard, 0, 2, SRCCOPY); + BitBlt(hdc, x+1, y+1, 1, height - 2, hdcDragCard, 1, 1, SRCCOPY); + + //draw the two bits to the right + BitBlt(hdc, x+width-2, y+1, 1, height - 2, hdcDragCard, width-2, 1, SRCCOPY); + BitBlt(hdc, x+width-1, y+2, 1, height - 4, hdcDragCard, width-1, 2, SRCCOPY); +} + +// +// Clip a card SHAPE - basically any rectangle +// with rounded corners +// +int ClipCard(HDC hdc, int x, int y, int width, int height) +{ + ExcludeClipRect(hdc, x+2, y, x+2+width-4, y+ height); + ExcludeClipRect(hdc, x, y+2, x+1, y+2+height-4); + ExcludeClipRect(hdc, x+1, y+1, x+2, y+1+height-2); + ExcludeClipRect(hdc, x+width-2, y+1, x+width-2+1, y+1+height-2); + ExcludeClipRect(hdc, x+width-1, y+2, x+width-1+1, y+2+height-4); + return 0; +} + +void CardRegion::Clip(HDC hdc) +{ + int numtoclip; + + if(fVisible == false) + return; + + Update(); //Update this stack's size+card count + numtoclip = nNumApparentCards; + + //if we are making this stack flash on/off, then only + //clip the stack for drawing if the flash is in its ON state + if(nFlashCount != 0) + { + if(fFlashVisible == FALSE) + numtoclip = 0; + } + + //if offset along a diagonal + if(xoffset != 0 && yoffset != 0 && cardstack.NumCards() != 0) + { + for(int j = 0; j < numtoclip; j ++) + { + ClipCard(hdc, xpos + xoffset * j, ypos + yoffset * j, __cardwidth, __cardheight); + } + } + //otherwise if just offset along a horizontal/vertical axis + else + { + if(yoffset < 0 && numtoclip > 0) + { + ClipCard(hdc, xpos, ypos-((numtoclip-1)*-yoffset), width, height); + } + else if(xoffset < 0 && numtoclip > 0) + { + ClipCard(hdc, xpos-((numtoclip-1)*-xoffset), ypos, width, height); + } + else + { + ClipCard(hdc, xpos, ypos, width, height); + } + } + +} + +void CardRegion::Render(HDC hdc) +{ + int cardnum = 0; + int numtodraw; + BOOL fDrawTips; + + Update(); //Update this stack's card count + size + + numtodraw = nNumApparentCards; + + if(nFlashCount != 0) + { + if(fFlashVisible == false) + numtodraw = 0; + } + + if(fVisible == 0) return; + + cardnum = cardstack.NumCards() - numtodraw; + int counter; + + for(counter = 0; counter < numtodraw; counter++) + { + int cardval; + + int x = xoffset * counter + xpos; + int y = yoffset * counter + ypos; + + //if about to draw last card, then actually draw the top card + if(counter == numtodraw - 1) cardnum = cardstack.NumCards() - 1; + + Card card = cardstack.cardlist[cardnum]; + cardval = card.Idx(); + + if(card.FaceDown()) + cardval = nBackCardIdx; //card-back + + //only draw the visible part of the card + if(counter < numtodraw - 1) + { + if(yoffset != 0 && xoffset != 0) + fDrawTips = FALSE; + else + fDrawTips = TRUE; + + if(yoffset != 0 && abs(xoffset) == 1 || xoffset != 0 && abs(yoffset) == 1) + fDrawTips = TRUE; + + //draw horizontal strips + if(yoffset > 0) + { + DrawHorzCardStrip(hdc, x, y, cardval, yoffset, fDrawTips); + } + else if(yoffset < 0) + { + DrawHorzCardStrip(hdc, x, y+__cardheight+yoffset, cardval, yoffset, fDrawTips); + } + + //draw some vertical bars + if(xoffset > 0) + { + DrawVertCardStrip(hdc, x, y, cardval, xoffset, fDrawTips); + } + else if(xoffset < 0) + { + DrawVertCardStrip(hdc, x+__cardwidth+xoffset, y, cardval, xoffset, fDrawTips); + } + + if(yoffset != 0 && xoffset != 0)//fDrawTips == FALSE) + { + //if we didn't draw any tips, then this is a 2-dim stack + //(i.e, it goes at a diagonal). + //in this case, we need to fill in the small triangle in + //each corner! + DrawCardCorner(hdc, x, y, cardval, xoffset, yoffset); + } + } + //if the top card, draw the whole thing + else + { + CardBlt(hdc, x, y, cardval); + } + + cardnum ++; + + } //end of index + + if(counter == 0) //if the cardstack is empty, then draw it that way + { + int x = xpos; + int y = ypos; + + switch(uEmptyImage) + { + default: case CS_EI_NONE: + //this wipes the RECT variable, so watch out! + //SetRect(&rect, x, y, x+__cardwidth, y+__cardheight); + //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd)); + parentWnd.PaintCardRgn(hdc, x, y, __cardwidth, __cardheight, x, y); + break; + + case CS_EI_SUNK: //case CS_EI_CIRC: case CS_EI_X: + DrawCard(hdc, x, y, __hdcPlaceHolder, __cardwidth, __cardheight); + break; + } + + } + + return; +} + +int calc_offset(int offset, int numcards, int numtodrag, int realvisible) +{ + if(offset >= 0) + return -offset * numcards; + else + return -offset * (numtodrag) + + -offset * (realvisible - 1); +} + +void CardRegion::PrepareDragBitmaps(int numtodrag) +{ + RECT rect; + HDC hdc; + int icard; + int numcards = cardstack.NumCards(); + int xoff, yoff; + + if(nThreedCount > 1) + { + PrepareDragBitmapsThreed(numtodrag); + return; + } + + //work out how big the bitmaps need to be + nDragCardWidth = (numtodrag - 1) * abs(xoffset) + __cardwidth; + nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight; + + //Create bitmap for the back-buffer + hdc = GetDC(NULL); + hdcBackGnd = CreateCompatibleDC(hdc); + hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight); + SelectObject(hdcBackGnd, hbmBackGnd); + + //Create bitmap for the drag-image + hdcDragCard = CreateCompatibleDC(hdc); + hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight); + SelectObject(hdcDragCard, hbmDragCard); + ReleaseDC(NULL, hdc); + + UseNicePalette(hdcBackGnd, __hPalette); + UseNicePalette(hdcDragCard, __hPalette); + + int realvisible = numcards / nThreedCount; + + //if(numcards > 0 && realvisible == 0) realvisible = 1; + int iwhichcard = numcards - 1; + if(nThreedCount == 1) iwhichcard = 0; + + //grab the first bit of background so we can prep the back buffer; do this by + //rendering the card stack (minus the card we are dragging) to the temporary + //background buffer, so it appears if we have lifted the card from the stack + //PaintRect(hdcBackGnd, &rect, crBackgnd); + SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight); + + xoff = calc_offset(xoffset, numcards, numtodrag, realvisible); + yoff = calc_offset(yoffset, numcards, numtodrag, realvisible); + + parentWnd.PaintCardRgn(hdcBackGnd, 0, 0, nDragCardWidth, nDragCardHeight, xpos - xoff, ypos - yoff); + + // + // Render the cardstack into the back-buffer. The stack + // has already had the dragcards removed, so just draw + // what is left + // + for(icard = 0; icard < realvisible; icard++) + { + Card card = cardstack.cardlist[iwhichcard]; + int nCardVal; + + nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx; + + xoff = xoffset * icard + calc_offset(xoffset, numcards, numtodrag, realvisible);//- xoffset * ((numcards+numtodrag) / nThreedCount - numtodrag); + yoff = yoffset * icard + calc_offset(yoffset, numcards, numtodrag, realvisible);//- yoffset * ((numcards+numtodrag) / nThreedCount - numtodrag); + + CardBlt(hdcBackGnd, xoff, yoff, nCardVal); + iwhichcard++; + } + + // + // If there are no cards under this one, just draw the place holder + // + if(numcards == 0) + { + int xoff = 0, yoff = 0; + + if(xoffset < 0) xoff = nDragCardWidth - __cardwidth; + if(yoffset < 0) yoff = nDragCardHeight - __cardheight; + + switch(uEmptyImage) + { + case CS_EI_NONE: + //No need to draw anything: We already cleared the + //back-buffer before the main loop.. + + //SetRect(&rc, xoff, yoff, xoff+ __cardwidth, yoff + __cardheight); + //PaintRect(hdcBackGnd, &rc, MAKE_PALETTERGB(crBackgnd)); + //parentWnd.PaintCardRgn(hdcBackGnd, xoff, yoff, __cardwidth, __cardheight, xpos, ypos);// + xoff, ypos + yoff); + break; + + case CS_EI_SUNK: + DrawCard(hdcBackGnd, xoff, yoff, __hdcPlaceHolder, __cardwidth, __cardheight); + break; + } + } + + // + // now render the drag-cards into the dragcard image + // + PaintRect(hdcDragCard, &rect, crBackgnd); + + for(icard = 0; icard < numtodrag; icard++) + { + int nCardVal; + + if(xoffset >= 0) xoff = xoffset * icard; + else xoff = -xoffset * (numtodrag - icard - 1); + + if(yoffset >= 0) yoff = yoffset * icard; + else yoff = -yoffset * (numtodrag - icard - 1); + + Card card = dragstack.cardlist[icard]; + + nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx; + + CardBlt(hdcDragCard, xoff, yoff, nCardVal); + } +} + +void CardRegion::PrepareDragBitmapsThreed(int numtodrag) +{ + RECT rect; + HDC hdc; + int icard; + int numunder = 0; + int iwhichcard; + + int numcards = cardstack.NumCards(); + + //work out how big the bitmaps need to be + nDragCardWidth = (numtodrag - 1) * abs(xoffset) + __cardwidth; + nDragCardHeight = (numtodrag - 1) * abs(yoffset) + __cardheight; + + //Create bitmap for the back-buffer + hdc = GetDC(NULL); + hdcBackGnd = CreateCompatibleDC(hdc); + hbmBackGnd = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight); + SelectObject(hdcBackGnd, hbmBackGnd); + + //create bitmap for the drag-image + hdcDragCard = CreateCompatibleDC(hdc); + hbmDragCard = CreateCompatibleBitmap(hdc, nDragCardWidth, nDragCardHeight); + SelectObject(hdcDragCard, hbmDragCard); + ReleaseDC(NULL, hdc); + + UseNicePalette(hdcBackGnd, __hPalette); + UseNicePalette(hdcDragCard, __hPalette); + + //grab the first bit of background so we can prep the back buffer; do this by + //rendering the card stack (minus the card we are dragging) to the temporary + //background buffer, so it appears if we have lifted the card from the stack + //--SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight); + //--PaintRect(hdcBackGnd, &rect, crBackgnd); + + int threedadjust = numcards % nThreedCount == 0; + + numunder = CalcApparentCards(numcards); + iwhichcard = (numcards+numtodrag) - numunder - 1; + if(nThreedCount == 1) iwhichcard = 0; + + int xoff = calc_offset(xoffset, numunder, numtodrag, numunder); + int yoff = calc_offset(yoffset, numunder, numtodrag, numunder); + + parentWnd.PaintCardRgn(hdcBackGnd, 0,0, nDragCardWidth,nDragCardHeight, xpos - xoff,ypos - yoff); + + // + // Render the cardstack into the back-buffer. The stack + // has already had the dragcards removed, so just draw + // what is left + // + for(icard = 0; icard < numunder; icard++) + { + Card card = cardstack.cardlist[iwhichcard]; + int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx; + + CardBlt(hdcBackGnd, + xoffset * icard - xoffset*(numunder-numtodrag+threedadjust), + yoffset * icard - yoffset*(numunder-numtodrag+threedadjust), + nCardVal); + + iwhichcard++; + } + + // + // If there are no cards under this one, just draw the place holder + // + if(numcards == 0) + { + switch(uEmptyImage) + { + case CS_EI_NONE: + //no need! we've already cleared the whole + //back-buffer before the main loop! + //SetRect(&rect, 0, 0, __cardwidth, __cardheight); + //PaintRect(hdcBackGnd, &rect, MAKE_PALETTERGB(crBackgnd)); + break; + + case CS_EI_SUNK: + DrawCard(hdcBackGnd, 0, 0, __hdcPlaceHolder, __cardwidth, __cardheight); + break; + + } + } + + // + // now render the drag-cards into the dragcard image + // + PaintRect(hdcDragCard, &rect, crBackgnd); + + for(icard = 0; icard < numtodrag; icard++) + { + Card card = dragstack.cardlist[icard]; + int nCardVal = card.FaceUp() ? card.Idx() : nBackCardIdx; + + CardBlt(hdcDragCard, xoffset * icard, yoffset * icard, nCardVal); + } +} + +void CardRegion::ReleaseDragBitmaps(void) +{ + //SelectObject(hdcBackGnd, hOld1); + DeleteObject(hbmBackGnd); + DeleteDC(hdcBackGnd); + + //SelectObject(hdcDragCard, hOld2); + DeleteObject(hbmDragCard); + DeleteDC(hdcDragCard); +} + + +void CardRegion::Redraw() +{ + HDC hdc = GetDC((HWND)parentWnd); + + Update(); + Render(hdc); + + ReleaseDC((HWND)parentWnd, hdc); +} diff --git a/rosapps/games/solitaire/cardlib/cardrgnmouse.cpp b/rosapps/games/solitaire/cardlib/cardrgnmouse.cpp index 317986acdce..a64bef2a1cd 100644 --- a/rosapps/games/solitaire/cardlib/cardrgnmouse.cpp +++ b/rosapps/games/solitaire/cardlib/cardrgnmouse.cpp @@ -1,642 +1,642 @@ -// -// CardLib - CardRegion mouse-related stuff -// -// Freeware -// Copyright J Brown 2001 -// -#include -#include -#include - -#include "cardlib.h" -#include "cardwindow.h" -#include "cardregion.h" - -#if 1 -#define TRACE(s) -#else -#define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s) -#endif - -double __CARDZOOMSPEED = 32; - -int ClipCard(HDC hdc, int x, int y, int width, int height); -void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height); - -#ifdef _DEBUG - -static pDebugClickProc DebugStackClickProc = 0; - -void CardLib_SetStackClickProc(pDebugClickProc proc) -{ - DebugStackClickProc = proc; -} - -#endif - -CardRegion *CardWindow::GetBestStack(int x, int y, int w, int h) -{ - int maxoverlap = 0; - int maxoverlapidx = -1; - - //find the stack which is most covered by the dropped - //cards. Only include those which allow drops. - // - for(int i = 0; i < nNumCardRegions; i++) - { - int percent = Regions[i]->GetOverlapRatio(x, y, w, h); - - //if this stack has the biggest coverage yet - if(percent > maxoverlap && Regions[i]->IsVisible()) - { - maxoverlap = percent; - maxoverlapidx = i; - } - } - - //if we found a stack to drop onto - if(maxoverlapidx != -1) - { - return Regions[maxoverlapidx]; - } - else - { - return 0; - } -} - -bool CardRegion::IsPointInStack(int x, int y) -{ - int axpos = xoffset < 0 ? xpos + (nNumApparentCards-1)*xoffset : xpos; - int aypos = yoffset < 0 ? ypos + (nNumApparentCards-1)*yoffset : ypos; - - if(x >= axpos && x < axpos + width && y >= aypos && y < aypos + height && fVisible) - return true; - else - return false; -} - -int CardRegion::GetNumDragCards(int x, int y) -{ - int cardindex = 0; //index from stack start - int maxidx; - - //make x,y relative to the stack's upper left corner - x -= xpos + (xoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * xoffset : 0); - y -= ypos + (yoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * yoffset : 0); - - //if stack is empty, cannot drag any cards from it - if(cardstack.NumCards() <= 0) - return 0; - - //see which card in the stack has been clicked on - //top-bottom ordering - if(yoffset > 0) - { - if(y < height - __cardheight) - cardindex = y / yoffset; - else - cardindex = cardstack.NumCards() - 1; - } - else if(yoffset < 0) - { - if(y < __cardheight) - cardindex = cardstack.NumCards() - 1; - else - cardindex = cardstack.NumCards() - ((y - __cardheight) / -yoffset) - 2; - } - else //yoffset == 0 - { - cardindex = cardstack.NumCards() - 1; - } - - maxidx = cardindex; - - //if left-right - if(xoffset > 0) - { - if(x < width - __cardwidth) - cardindex = x / xoffset; - else - cardindex = cardstack.NumCards() - 1; - } - else if(xoffset < 0) - { - if(x < __cardwidth) - cardindex = cardstack.NumCards() - 1; - else - cardindex = cardstack.NumCards() - ((x - __cardwidth) / -xoffset) - 2; - } - else - { - cardindex = cardstack.NumCards() - 1; - } - - if(cardindex > maxidx) cardindex = maxidx; - - if(cardindex > cardstack.NumCards()) - cardindex = 1; - - //if are trying to drag too many cards at once - return cardstack.NumCards() - cardindex; -} - -bool CardRegion::CanDragCards(int iNumCards) -{ - if(iNumCards <= 0) return false; - if(nThreedCount > 1 && iNumCards > 1) return false; - - if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0) - { -// TRACE("Failed to gain access to card stack\n"); - return false; - } - - ReleaseMutex(mxlock); - - switch(uDragRule) - { - case CS_DRAG_ALL: - return true; - - case CS_DRAG_TOP: - - if(iNumCards == 1) - return true; - else - return false; - - case CS_DRAG_NONE: - return false; - - case CS_DRAG_CALLBACK: - - if(CanDragCallback) - { - return CanDragCallback(*this, iNumCards); - } - else - { - return false; - } - - default: - return false; - } -} - -bool CardRegion::CanDropCards(CardStack &cards) -{ - if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0) - { - return false; - } - - ReleaseMutex(mxlock); - - switch(uDropRule) - { - case CS_DROP_ALL: - return true; - - case CS_DROP_NONE: - return false; - - case CS_DROP_CALLBACK: - - if(CanDropCallback) - { - return CanDropCallback(*this, cards); - } - else - { - return false; - } - - default: - return false; - } -} - -bool CardRegion::OnLButtonDblClk(int x, int y) -{ - iNumDragCards = GetNumDragCards(x, y); - - if(DblClickCallback) - DblClickCallback(*this, iNumDragCards); - - return true; -} - -bool CardRegion::OnLButtonDown(int x, int y) -{ - iNumDragCards = GetNumDragCards(x, y); - -#ifdef _DEBUG - if(DebugStackClickProc) - { - if(!DebugStackClickProc(*this)) - return false; - } -#endif - - if(ClickCallback) - ClickCallback(*this, iNumDragCards); - - if(CanDragCards(iNumDragCards) != false) - { - - //offset of the mouse cursor relative to the top-left corner - //of the cards that are being dragged - mousexoffset = x - xpos - xoffset * (nNumApparentCards - iNumDragCards); - mouseyoffset = y - ypos - yoffset * (nNumApparentCards - iNumDragCards); - - if(xoffset < 0) - mousexoffset += -xoffset * (iNumDragCards - 1); - - if(yoffset < 0) - mouseyoffset += -yoffset * (iNumDragCards - 1); - - //remove the cards from the source stack - dragstack = cardstack.Pop(iNumDragCards); - - //prepare the back buffer, and the drag image - PrepareDragBitmaps(iNumDragCards); - - oldx = x - mousexoffset; - oldy = y - mouseyoffset; - - Update(); //Update this stack's card count + size - - SetCapture((HWND)parentWnd); - - //set AFTER settings the dragstack... - fMouseDragging = true; - - return true; - } - - return false; -} - -bool CardRegion::OnLButtonUp(int x, int y) -{ - CardRegion *pDestStack = 0; - HDC hdc; - int dropstackid = CS_DROPZONE_NODROP; - - RECT dragrect; - DropZone *dropzone; - - fMouseDragging = false; - - //first of all, see if any drop zones have been registered - SetRect(&dragrect, x-mousexoffset, y-mouseyoffset, x-mousexoffset+nDragCardWidth, y-mouseyoffset+nDragCardHeight); - - dropzone = parentWnd.GetDropZoneFromRect(&dragrect); - - if(dropzone) - { - dropstackid = dropzone->DropCards(dragstack); - - if(dropstackid != CS_DROPZONE_NODROP) - pDestStack = parentWnd.CardRegionFromId(dropstackid); - else - pDestStack = 0; - } - else - { - pDestStack = parentWnd.GetBestStack(x - mousexoffset, y - mouseyoffset, nDragCardWidth, nDragCardHeight); - } - - // If have found a stack to drop onto - // - TRACE ( "can I drop card?\n" ); - if(pDestStack && pDestStack->CanDropCards(dragstack)) - { - TRACE ( "yes, dropping card\n" ); - hdc = GetDC((HWND)parentWnd); - // UseNicePalette(hdc); - ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, pDestStack); - ReleaseDC((HWND)parentWnd, hdc); - - // - //add the cards to the destination stack - // - CardStack temp = pDestStack->GetCardStack(); - temp.Push(dragstack); - - pDestStack->SetCardStack(temp); -// pDestStack->Update(); //Update this stack's card count + size -// pDestStack->UpdateFaceDir(temp); - - // Call the remove callback on THIS stack, if one is specified - // - if(RemoveCallback) - RemoveCallback(*this, iNumDragCards); - - // Call the add callback, if one is specified - // - if(pDestStack->AddCallback) - pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);//index, deststack->numcards); - - RedrawIfNotDim(pDestStack, true); - TRACE ( "done dropping card\n" ); - } - - // - // Otherwise, let the cards snap back onto this stack - // - else - { - TRACE ( "no, putting card back\n" ); - hdc = GetDC((HWND)parentWnd); - TRACE ( "calling ZoomCard()\n" ); - ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this); - TRACE ( "cardstack += dragstack\n" ); - cardstack += dragstack; - TRACE ( "calling ReleaseDC()\n" ); - ReleaseDC((HWND)parentWnd, hdc); - - TRACE ( "calling Update()\n" ); - Update(); //Update this stack's card count + size - TRACE ( "done putting card back\n" ); - } - - ReleaseDragBitmaps(); - ReleaseCapture(); - - TRACE ( "OnLButtonUp() done\n" ); - return true; -} - -bool CardRegion::OnMouseMove(int x, int y) -{ - HDC hdc; - - hdc = GetDC((HWND)parentWnd); - - x -= mousexoffset; - y -= mouseyoffset; - - MoveDragCardTo(hdc, x, y); - - //BitBlt(hdc, nDragCardWidth+10, 0, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY); - //BitBlt(hdc, 0, 0, nDragCardWidth, nDragCardHeight, hdcDragCard, 0, 0, SRCCOPY); - - ReleaseDC((HWND)parentWnd, hdc); - - oldx = x; - oldy = y; - - return true; -} - -// -// There is a bug in BitBlt when the source x,y -// become < 0. So this wrapper function simply adjusts -// the coords so that we never try to blt in from this range -// -BOOL ClippedBitBlt(HDC hdcDest, int x, int y, int width, int height, HDC hdcSrc, int srcx, int srcy, DWORD dwROP) -{ - if(srcx < 0) - { - x = 0 - srcx; - width = width + srcx; - srcx = 0; - } - - if(srcy < 0) - { - y = 0 - srcy; - height = height + srcy; - srcy = 0; - } - - return BitBlt(hdcDest, x, y, width, height, hdcSrc, srcx, srcy, dwROP); -} - -void CardRegion::MoveDragCardTo(HDC hdc, int x, int y) -{ - RECT inter, rect1, rect2; - - //mask off the new position of the drag-card, so - //that it will not be painted over - ClipCard(hdc, x, y, nDragCardWidth, nDragCardHeight); - - //restore the area covered by the card at its previous position - BitBlt(hdc, oldx, oldy, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY); - - //remove clipping so we can draw the card at its new place - SelectClipRgn(hdc, NULL); - - //if the card's old and new positions overlap, then we - //need some funky code to update the "saved background" image, - SetRect(&rect1, oldx, oldy, oldx+nDragCardWidth, oldy+nDragCardHeight); - SetRect(&rect2, x, y, x+nDragCardWidth, y+nDragCardHeight); - - if(IntersectRect(&inter, &rect1, &rect2)) - { - int interwidth = inter.right-inter.left; - int interheight = inter.bottom-inter.top; - int destx, desty, srcx, srcy; - - if(rect2.left > rect1.left) - { - destx = 0; srcx = nDragCardWidth - interwidth; - } - else - { - destx = nDragCardWidth - interwidth; srcx = 0; - } - - if(rect2.top > rect1.top) - { - desty = 0; srcy = nDragCardHeight - interheight; - } - else - { - desty = nDragCardHeight - interheight; srcy = 0; - } - - //shift the bit we didn't use for the restore (due to the clipping) - //into the opposite corner - BitBlt(hdcBackGnd, destx,desty, interwidth, interheight, hdcBackGnd, srcx, srcy, SRCCOPY); - - ExcludeClipRect(hdcBackGnd, destx, desty, destx+interwidth, desty+interheight); - - //this bit requires us to clip the BitBlt (from screen to background) - //as BitBlt is a bit buggy it seems - ClippedBitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY); - SelectClipRgn(hdcBackGnd, NULL); - } - else - { - BitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY); - } - - //finally draw the card to the screen - DrawCard(hdc, x, y, hdcDragCard, nDragCardWidth, nDragCardHeight); -} - - -//extern "C" int _fltused(void) { return 0; } -//extern "C" int _ftol(void) { return 0; } - -// -// Better do this in fixed-point, to stop -// VC from linking in floatingpoint-long conversions -// -//#define FIXED_PREC_MOVE -#ifdef FIXED_PREC_MOVE -#define PRECISION 12 -void ZoomCard(HDC hdc, int xpos, int ypos, CARDSTACK *dest) -{ - long dx, dy, x , y; - - - int apparentcards; - x = xpos << PRECISION; y = ypos << PRECISION; - - oldx = (int)xpos; - oldy = (int)ypos; - - apparentcards=dest->numcards/dest->threedcount; - - int idestx = dest->xpos + dest->xoffset * (apparentcards);// - iNumDragCards); - int idesty = dest->ypos + dest->yoffset * (apparentcards);// - iNumDragCards); - - //normalise the motion vector - dx = (idestx<>PRECISION; - iy = (int)y>>PRECISION; - if(dx < 0 && ix < idestx) ix = idestx; - else if(dx > 0 && ix > idestx) ix = idestx; - - if(dy < 0 && iy < idesty) iy = idesty; - else if(dy > 0 && iy > idesty) iy = idesty; - - MoveDragCardTo(hdc, ix, iy); - - if(ix == idestx && iy == idesty) - break; - - oldx = (int)x >> PRECISION; - oldy = (int)y >> PRECISION; - - //dx *= 1.2; - //dy *= 1.2; - - Sleep(10); - } -} -#else -void CardRegion::ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *pDestStack) -{ - TRACE ( "ENTER ZoomCard()\n" ); - double dx, dy, x ,y; - int apparentcards; - x = (double)xpos; y = (double)ypos; - - oldx = (int)x; - oldy = (int)y; - - apparentcards = pDestStack->cardstack.NumCards() / pDestStack->nThreedCount; - - int idestx = pDestStack->xpos + pDestStack->xoffset * (apparentcards); - int idesty = pDestStack->ypos + pDestStack->yoffset * (apparentcards); - - if(pDestStack->yoffset < 0) - idesty += pDestStack->yoffset * (iNumDragCards-1); - - if(pDestStack->xoffset < 0) - idestx += pDestStack->xoffset * (iNumDragCards-1); - - //normalise the motion vector - dx = idestx - x; - dy = idesty - y; - if ( fabs(dx) + fabs(dy) < 0.001f ) - { - MoveDragCardTo(hdc, idestx, idesty); - return; - } - double recip = 1.0 / sqrt(dx*dx + dy*dy); - dx *= recip * __CARDZOOMSPEED; dy *= recip * __CARDZOOMSPEED; - - //if(dx < 0) dxinc = 1.001; else - - for(;;) - { - bool attarget = true; - int ix, iy; - x += dx; - y += dy; - - ix = (int)x; - iy = (int)y; - - if(dx < 0.0 && ix < idestx) ix = idestx; - else if(dx > 0.0 && ix > idestx) ix = idestx; - else attarget = false; - - if(dy < 0.0 && iy < idesty) iy = idesty; - else if(dy > 0.0 && iy > idesty) iy = idesty; - else attarget = false; - - //if the target stack wants the drag cards drawn differently - //to how they are, then redraw the drag card image just before - //the cards land - /*if(attarget == true) - { - for(int i = 0; i < iNumDragCards; i++) - { - int xdraw = pDestStack->xoffset*i; - int ydraw = pDestStack->yoffset*i; - - if(pDestStack->yoffset < 0) - ydraw = -pDestStack->yoffset * (iNumDragCards-i-1); - if(pDestStack->xoffset < 0) - xdraw = -pDestStack->xoffset * (iNumDragCards-i-1); - - if(pDestStack->facedirection == CS_FACEUP && - pDestStack->numcards+i >= dest->numfacedown) - { - //cdtDraw(hdcDragCard, xdraw, ydraw, iDragCards[i], ectFACES, 0); - } - else - { - //cdtDraw(hdcDragCard, xdraw, ydraw, CARDSTACK::backcard, ectBACKS, 0); - } - } - }*/ - - MoveDragCardTo(hdc, ix, iy); - - if(attarget || ix == idestx && iy == idesty) - break; - - oldx = (int)x; - oldy = (int)y; - - //dx *= 1.2; - //dy *= 1.2; - - Sleep(10); - } - TRACE ( "EXIT ZoomCard()\n" ); -} -#endif +// +// CardLib - CardRegion mouse-related stuff +// +// Freeware +// Copyright J Brown 2001 +// +#include +#include +#include + +#include "cardlib.h" +#include "cardwindow.h" +#include "cardregion.h" + +#if 1 +#define TRACE(s) +#else +#define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s) +#endif + +double __CARDZOOMSPEED = 32; + +int ClipCard(HDC hdc, int x, int y, int width, int height); +void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height); + +#ifdef _DEBUG + +static pDebugClickProc DebugStackClickProc = 0; + +void CardLib_SetStackClickProc(pDebugClickProc proc) +{ + DebugStackClickProc = proc; +} + +#endif + +CardRegion *CardWindow::GetBestStack(int x, int y, int w, int h) +{ + int maxoverlap = 0; + int maxoverlapidx = -1; + + //find the stack which is most covered by the dropped + //cards. Only include those which allow drops. + // + for(int i = 0; i < nNumCardRegions; i++) + { + int percent = Regions[i]->GetOverlapRatio(x, y, w, h); + + //if this stack has the biggest coverage yet + if(percent > maxoverlap && Regions[i]->IsVisible()) + { + maxoverlap = percent; + maxoverlapidx = i; + } + } + + //if we found a stack to drop onto + if(maxoverlapidx != -1) + { + return Regions[maxoverlapidx]; + } + else + { + return 0; + } +} + +bool CardRegion::IsPointInStack(int x, int y) +{ + int axpos = xoffset < 0 ? xpos + (nNumApparentCards-1)*xoffset : xpos; + int aypos = yoffset < 0 ? ypos + (nNumApparentCards-1)*yoffset : ypos; + + if(x >= axpos && x < axpos + width && y >= aypos && y < aypos + height && fVisible) + return true; + else + return false; +} + +int CardRegion::GetNumDragCards(int x, int y) +{ + int cardindex = 0; //index from stack start + int maxidx; + + //make x,y relative to the stack's upper left corner + x -= xpos + (xoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * xoffset : 0); + y -= ypos + (yoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * yoffset : 0); + + //if stack is empty, cannot drag any cards from it + if(cardstack.NumCards() <= 0) + return 0; + + //see which card in the stack has been clicked on + //top-bottom ordering + if(yoffset > 0) + { + if(y < height - __cardheight) + cardindex = y / yoffset; + else + cardindex = cardstack.NumCards() - 1; + } + else if(yoffset < 0) + { + if(y < __cardheight) + cardindex = cardstack.NumCards() - 1; + else + cardindex = cardstack.NumCards() - ((y - __cardheight) / -yoffset) - 2; + } + else //yoffset == 0 + { + cardindex = cardstack.NumCards() - 1; + } + + maxidx = cardindex; + + //if left-right + if(xoffset > 0) + { + if(x < width - __cardwidth) + cardindex = x / xoffset; + else + cardindex = cardstack.NumCards() - 1; + } + else if(xoffset < 0) + { + if(x < __cardwidth) + cardindex = cardstack.NumCards() - 1; + else + cardindex = cardstack.NumCards() - ((x - __cardwidth) / -xoffset) - 2; + } + else + { + cardindex = cardstack.NumCards() - 1; + } + + if(cardindex > maxidx) cardindex = maxidx; + + if(cardindex > cardstack.NumCards()) + cardindex = 1; + + //if are trying to drag too many cards at once + return cardstack.NumCards() - cardindex; +} + +bool CardRegion::CanDragCards(int iNumCards) +{ + if(iNumCards <= 0) return false; + if(nThreedCount > 1 && iNumCards > 1) return false; + + if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0) + { +// TRACE("Failed to gain access to card stack\n"); + return false; + } + + ReleaseMutex(mxlock); + + switch(uDragRule) + { + case CS_DRAG_ALL: + return true; + + case CS_DRAG_TOP: + + if(iNumCards == 1) + return true; + else + return false; + + case CS_DRAG_NONE: + return false; + + case CS_DRAG_CALLBACK: + + if(CanDragCallback) + { + return CanDragCallback(*this, iNumCards); + } + else + { + return false; + } + + default: + return false; + } +} + +bool CardRegion::CanDropCards(CardStack &cards) +{ + if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0) + { + return false; + } + + ReleaseMutex(mxlock); + + switch(uDropRule) + { + case CS_DROP_ALL: + return true; + + case CS_DROP_NONE: + return false; + + case CS_DROP_CALLBACK: + + if(CanDropCallback) + { + return CanDropCallback(*this, cards); + } + else + { + return false; + } + + default: + return false; + } +} + +bool CardRegion::OnLButtonDblClk(int x, int y) +{ + iNumDragCards = GetNumDragCards(x, y); + + if(DblClickCallback) + DblClickCallback(*this, iNumDragCards); + + return true; +} + +bool CardRegion::OnLButtonDown(int x, int y) +{ + iNumDragCards = GetNumDragCards(x, y); + +#ifdef _DEBUG + if(DebugStackClickProc) + { + if(!DebugStackClickProc(*this)) + return false; + } +#endif + + if(ClickCallback) + ClickCallback(*this, iNumDragCards); + + if(CanDragCards(iNumDragCards) != false) + { + + //offset of the mouse cursor relative to the top-left corner + //of the cards that are being dragged + mousexoffset = x - xpos - xoffset * (nNumApparentCards - iNumDragCards); + mouseyoffset = y - ypos - yoffset * (nNumApparentCards - iNumDragCards); + + if(xoffset < 0) + mousexoffset += -xoffset * (iNumDragCards - 1); + + if(yoffset < 0) + mouseyoffset += -yoffset * (iNumDragCards - 1); + + //remove the cards from the source stack + dragstack = cardstack.Pop(iNumDragCards); + + //prepare the back buffer, and the drag image + PrepareDragBitmaps(iNumDragCards); + + oldx = x - mousexoffset; + oldy = y - mouseyoffset; + + Update(); //Update this stack's card count + size + + SetCapture((HWND)parentWnd); + + //set AFTER settings the dragstack... + fMouseDragging = true; + + return true; + } + + return false; +} + +bool CardRegion::OnLButtonUp(int x, int y) +{ + CardRegion *pDestStack = 0; + HDC hdc; + int dropstackid = CS_DROPZONE_NODROP; + + RECT dragrect; + DropZone *dropzone; + + fMouseDragging = false; + + //first of all, see if any drop zones have been registered + SetRect(&dragrect, x-mousexoffset, y-mouseyoffset, x-mousexoffset+nDragCardWidth, y-mouseyoffset+nDragCardHeight); + + dropzone = parentWnd.GetDropZoneFromRect(&dragrect); + + if(dropzone) + { + dropstackid = dropzone->DropCards(dragstack); + + if(dropstackid != CS_DROPZONE_NODROP) + pDestStack = parentWnd.CardRegionFromId(dropstackid); + else + pDestStack = 0; + } + else + { + pDestStack = parentWnd.GetBestStack(x - mousexoffset, y - mouseyoffset, nDragCardWidth, nDragCardHeight); + } + + // If have found a stack to drop onto + // + TRACE ( "can I drop card?\n" ); + if(pDestStack && pDestStack->CanDropCards(dragstack)) + { + TRACE ( "yes, dropping card\n" ); + hdc = GetDC((HWND)parentWnd); + // UseNicePalette(hdc); + ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, pDestStack); + ReleaseDC((HWND)parentWnd, hdc); + + // + //add the cards to the destination stack + // + CardStack temp = pDestStack->GetCardStack(); + temp.Push(dragstack); + + pDestStack->SetCardStack(temp); +// pDestStack->Update(); //Update this stack's card count + size +// pDestStack->UpdateFaceDir(temp); + + // Call the remove callback on THIS stack, if one is specified + // + if(RemoveCallback) + RemoveCallback(*this, iNumDragCards); + + // Call the add callback, if one is specified + // + if(pDestStack->AddCallback) + pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);//index, deststack->numcards); + + RedrawIfNotDim(pDestStack, true); + TRACE ( "done dropping card\n" ); + } + + // + // Otherwise, let the cards snap back onto this stack + // + else + { + TRACE ( "no, putting card back\n" ); + hdc = GetDC((HWND)parentWnd); + TRACE ( "calling ZoomCard()\n" ); + ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this); + TRACE ( "cardstack += dragstack\n" ); + cardstack += dragstack; + TRACE ( "calling ReleaseDC()\n" ); + ReleaseDC((HWND)parentWnd, hdc); + + TRACE ( "calling Update()\n" ); + Update(); //Update this stack's card count + size + TRACE ( "done putting card back\n" ); + } + + ReleaseDragBitmaps(); + ReleaseCapture(); + + TRACE ( "OnLButtonUp() done\n" ); + return true; +} + +bool CardRegion::OnMouseMove(int x, int y) +{ + HDC hdc; + + hdc = GetDC((HWND)parentWnd); + + x -= mousexoffset; + y -= mouseyoffset; + + MoveDragCardTo(hdc, x, y); + + //BitBlt(hdc, nDragCardWidth+10, 0, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY); + //BitBlt(hdc, 0, 0, nDragCardWidth, nDragCardHeight, hdcDragCard, 0, 0, SRCCOPY); + + ReleaseDC((HWND)parentWnd, hdc); + + oldx = x; + oldy = y; + + return true; +} + +// +// There is a bug in BitBlt when the source x,y +// become < 0. So this wrapper function simply adjusts +// the coords so that we never try to blt in from this range +// +BOOL ClippedBitBlt(HDC hdcDest, int x, int y, int width, int height, HDC hdcSrc, int srcx, int srcy, DWORD dwROP) +{ + if(srcx < 0) + { + x = 0 - srcx; + width = width + srcx; + srcx = 0; + } + + if(srcy < 0) + { + y = 0 - srcy; + height = height + srcy; + srcy = 0; + } + + return BitBlt(hdcDest, x, y, width, height, hdcSrc, srcx, srcy, dwROP); +} + +void CardRegion::MoveDragCardTo(HDC hdc, int x, int y) +{ + RECT inter, rect1, rect2; + + //mask off the new position of the drag-card, so + //that it will not be painted over + ClipCard(hdc, x, y, nDragCardWidth, nDragCardHeight); + + //restore the area covered by the card at its previous position + BitBlt(hdc, oldx, oldy, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY); + + //remove clipping so we can draw the card at its new place + SelectClipRgn(hdc, NULL); + + //if the card's old and new positions overlap, then we + //need some funky code to update the "saved background" image, + SetRect(&rect1, oldx, oldy, oldx+nDragCardWidth, oldy+nDragCardHeight); + SetRect(&rect2, x, y, x+nDragCardWidth, y+nDragCardHeight); + + if(IntersectRect(&inter, &rect1, &rect2)) + { + int interwidth = inter.right-inter.left; + int interheight = inter.bottom-inter.top; + int destx, desty, srcx, srcy; + + if(rect2.left > rect1.left) + { + destx = 0; srcx = nDragCardWidth - interwidth; + } + else + { + destx = nDragCardWidth - interwidth; srcx = 0; + } + + if(rect2.top > rect1.top) + { + desty = 0; srcy = nDragCardHeight - interheight; + } + else + { + desty = nDragCardHeight - interheight; srcy = 0; + } + + //shift the bit we didn't use for the restore (due to the clipping) + //into the opposite corner + BitBlt(hdcBackGnd, destx,desty, interwidth, interheight, hdcBackGnd, srcx, srcy, SRCCOPY); + + ExcludeClipRect(hdcBackGnd, destx, desty, destx+interwidth, desty+interheight); + + //this bit requires us to clip the BitBlt (from screen to background) + //as BitBlt is a bit buggy it seems + ClippedBitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY); + SelectClipRgn(hdcBackGnd, NULL); + } + else + { + BitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY); + } + + //finally draw the card to the screen + DrawCard(hdc, x, y, hdcDragCard, nDragCardWidth, nDragCardHeight); +} + + +//extern "C" int _fltused(void) { return 0; } +//extern "C" int _ftol(void) { return 0; } + +// +// Better do this in fixed-point, to stop +// VC from linking in floatingpoint-long conversions +// +//#define FIXED_PREC_MOVE +#ifdef FIXED_PREC_MOVE +#define PRECISION 12 +void ZoomCard(HDC hdc, int xpos, int ypos, CARDSTACK *dest) +{ + long dx, dy, x , y; + + + int apparentcards; + x = xpos << PRECISION; y = ypos << PRECISION; + + oldx = (int)xpos; + oldy = (int)ypos; + + apparentcards=dest->numcards/dest->threedcount; + + int idestx = dest->xpos + dest->xoffset * (apparentcards);// - iNumDragCards); + int idesty = dest->ypos + dest->yoffset * (apparentcards);// - iNumDragCards); + + //normalise the motion vector + dx = (idestx<>PRECISION; + iy = (int)y>>PRECISION; + if(dx < 0 && ix < idestx) ix = idestx; + else if(dx > 0 && ix > idestx) ix = idestx; + + if(dy < 0 && iy < idesty) iy = idesty; + else if(dy > 0 && iy > idesty) iy = idesty; + + MoveDragCardTo(hdc, ix, iy); + + if(ix == idestx && iy == idesty) + break; + + oldx = (int)x >> PRECISION; + oldy = (int)y >> PRECISION; + + //dx *= 1.2; + //dy *= 1.2; + + Sleep(10); + } +} +#else +void CardRegion::ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *pDestStack) +{ + TRACE ( "ENTER ZoomCard()\n" ); + double dx, dy, x ,y; + int apparentcards; + x = (double)xpos; y = (double)ypos; + + oldx = (int)x; + oldy = (int)y; + + apparentcards = pDestStack->cardstack.NumCards() / pDestStack->nThreedCount; + + int idestx = pDestStack->xpos + pDestStack->xoffset * (apparentcards); + int idesty = pDestStack->ypos + pDestStack->yoffset * (apparentcards); + + if(pDestStack->yoffset < 0) + idesty += pDestStack->yoffset * (iNumDragCards-1); + + if(pDestStack->xoffset < 0) + idestx += pDestStack->xoffset * (iNumDragCards-1); + + //normalise the motion vector + dx = idestx - x; + dy = idesty - y; + if ( fabs(dx) + fabs(dy) < 0.001f ) + { + MoveDragCardTo(hdc, idestx, idesty); + return; + } + double recip = 1.0 / sqrt(dx*dx + dy*dy); + dx *= recip * __CARDZOOMSPEED; dy *= recip * __CARDZOOMSPEED; + + //if(dx < 0) dxinc = 1.001; else + + for(;;) + { + bool attarget = true; + int ix, iy; + x += dx; + y += dy; + + ix = (int)x; + iy = (int)y; + + if(dx < 0.0 && ix < idestx) ix = idestx; + else if(dx > 0.0 && ix > idestx) ix = idestx; + else attarget = false; + + if(dy < 0.0 && iy < idesty) iy = idesty; + else if(dy > 0.0 && iy > idesty) iy = idesty; + else attarget = false; + + //if the target stack wants the drag cards drawn differently + //to how they are, then redraw the drag card image just before + //the cards land + /*if(attarget == true) + { + for(int i = 0; i < iNumDragCards; i++) + { + int xdraw = pDestStack->xoffset*i; + int ydraw = pDestStack->yoffset*i; + + if(pDestStack->yoffset < 0) + ydraw = -pDestStack->yoffset * (iNumDragCards-i-1); + if(pDestStack->xoffset < 0) + xdraw = -pDestStack->xoffset * (iNumDragCards-i-1); + + if(pDestStack->facedirection == CS_FACEUP && + pDestStack->numcards+i >= dest->numfacedown) + { + //cdtDraw(hdcDragCard, xdraw, ydraw, iDragCards[i], ectFACES, 0); + } + else + { + //cdtDraw(hdcDragCard, xdraw, ydraw, CARDSTACK::backcard, ectBACKS, 0); + } + } + }*/ + + MoveDragCardTo(hdc, ix, iy); + + if(attarget || ix == idestx && iy == idesty) + break; + + oldx = (int)x; + oldy = (int)y; + + //dx *= 1.2; + //dy *= 1.2; + + Sleep(10); + } + TRACE ( "EXIT ZoomCard()\n" ); +} +#endif diff --git a/rosapps/games/solitaire/cardlib/cardstack.cpp b/rosapps/games/solitaire/cardlib/cardstack.cpp index 06b9f2583d4..8273b232401 100644 --- a/rosapps/games/solitaire/cardlib/cardstack.cpp +++ b/rosapps/games/solitaire/cardlib/cardstack.cpp @@ -1,237 +1,237 @@ -// -// CardLib - CardStack class -// -// Freeware -// Copyright J Brown 2001 -// -#include -#include - -#include "cardstack.h" - -Card &CardStack::operator[] (size_t index) -{ - if(index >= (size_t)nNumCards) index = nNumCards - 1; - return cardlist[nNumCards - index - 1]; -} - -const Card &CardStack::operator[] (size_t index) const -{ - if(index >= (size_t)nNumCards) index = nNumCards - 1; - return cardlist[nNumCards - index - 1]; -} - -// Subscripting operator for a constant sequence -// -/*Card CardStack::operator[] (size_t index) const -{ - return cardlist[index]; -}*/ - -// -// Subscripting operator for a non-const sequence -// -/*CardStack::ref CardStack::operator[] (size_t index) -{ - return ref(this, index); -}*/ - -void CardStack::Clear() -{ - nNumCards = 0; -} - -void CardStack::NewDeck() -{ - nNumCards = 52; - - for(int i = 0; i < 52; i++) - cardlist[i].nValue = i; -} - -void CardStack::Shuffle() -{ - int src, dest; - Card temp; - - //shuffle 8 times.. - for(int i = 0; i < 8; i++) - for(dest = nNumCards - 1; dest > 0; dest--) - { - //want to do this: - // bad: src = rand() % (dest + 1) - // good: src = rand() / (RAND_MAX / (dest+1) + 1) - - //positions from 0 to dest - src = rand() / (RAND_MAX / (dest+1) + 1); - - //swap the cards - temp = cardlist[src]; - cardlist[src] = cardlist[dest]; - cardlist[dest] = temp; - } -} - -void CardStack::Reverse() -{ - for(int i = 0; i < nNumCards / 2; i++) - { - Card temp = cardlist[i]; - cardlist[i] = cardlist[nNumCards - i - 1]; - cardlist[nNumCards - i - 1] = temp; - } -} - -void CardStack::Push(const Card card) -{ - if(nNumCards < MAX_CARDSTACK_SIZE) - cardlist[nNumCards++] = card; -} - -void CardStack::Push(const CardStack &cardstack) -{ - if(nNumCards + cardstack.nNumCards < MAX_CARDSTACK_SIZE) - { - int num = cardstack.NumCards(); - - for(int i = 0; i < num; i++) - cardlist[nNumCards++] = cardstack.cardlist[i]; - } -} - -CardStack& CardStack::operator += (Card card) -{ - Push(card); - return *this; -} - -CardStack& CardStack::operator += (CardStack &cs) -{ - Push(cs); - return *this; -} - -CardStack CardStack::operator + (Card card) -{ - CardStack poo = *this; - poo.Push(card); - return poo; -} - -CardStack CardStack::operator + (CardStack &cs) -{ - CardStack poo = *this; - poo.Push(cs); - return poo; -} - - -Card CardStack::Pop() -{ - if(nNumCards > 0) - return cardlist[--nNumCards]; - else - return 0; -} - -CardStack CardStack::Pop(int items) -{ - if(items <= nNumCards && nNumCards > 0) - { - CardStack cs(*this, nNumCards - items); - - nNumCards -= items; - - return cs; - } - else - { - return CardStack(); - } -} - -Card CardStack::Top() -{ - if(nNumCards > 0) - return cardlist[nNumCards - 1]; - else - return 0; -} - -CardStack CardStack::Top(int items) -{ - if(items <= nNumCards && nNumCards > 0) - { - return CardStack (*this, nNumCards - items); - } - else - { - return CardStack(); - } - -} - -Card CardStack::RemoveCard(size_t index) -{ - if(nNumCards == 0 || index >= (size_t)nNumCards) - return 0; - - //put index into reverse range.. - index = nNumCards - index - 1; - - Card temp = cardlist[index]; - - nNumCards--; - - for(size_t i = index; i < (size_t)nNumCards; i++) - { - cardlist[i] = cardlist[i+1]; - } - - return temp; -} - -void CardStack::InsertCard(size_t index, Card card) -{ - if(nNumCards == MAX_CARDSTACK_SIZE) - return; - - if(index > (size_t)nNumCards) - return; - - if((size_t)nNumCards == index) - { - cardlist[nNumCards] = card; - nNumCards++; - return; - } - - //put index into reverse range.. - index = nNumCards - index - 1; - - nNumCards++; - - //make room for the card - for(size_t i = nNumCards; i > index; i--) - { - cardlist[i] = cardlist[i - 1]; - } - - cardlist[index] = card; -} - - -void CardStack::Print() -{ -// for(int i = 0; i < nNumCards; i++) -// cout << cardlist[i].HiVal() << " "; -} - -CardStack::CardStack(CardStack ©this, size_t fromindex) -{ - nNumCards = copythis.nNumCards - fromindex; - - for(int i = 0; i < nNumCards; i++) - cardlist[i] = copythis.cardlist[fromindex + i]; -} - +// +// CardLib - CardStack class +// +// Freeware +// Copyright J Brown 2001 +// +#include +#include + +#include "cardstack.h" + +Card &CardStack::operator[] (size_t index) +{ + if(index >= (size_t)nNumCards) index = nNumCards - 1; + return cardlist[nNumCards - index - 1]; +} + +const Card &CardStack::operator[] (size_t index) const +{ + if(index >= (size_t)nNumCards) index = nNumCards - 1; + return cardlist[nNumCards - index - 1]; +} + +// Subscripting operator for a constant sequence +// +/*Card CardStack::operator[] (size_t index) const +{ + return cardlist[index]; +}*/ + +// +// Subscripting operator for a non-const sequence +// +/*CardStack::ref CardStack::operator[] (size_t index) +{ + return ref(this, index); +}*/ + +void CardStack::Clear() +{ + nNumCards = 0; +} + +void CardStack::NewDeck() +{ + nNumCards = 52; + + for(int i = 0; i < 52; i++) + cardlist[i].nValue = i; +} + +void CardStack::Shuffle() +{ + int src, dest; + Card temp; + + //shuffle 8 times.. + for(int i = 0; i < 8; i++) + for(dest = nNumCards - 1; dest > 0; dest--) + { + //want to do this: + // bad: src = rand() % (dest + 1) + // good: src = rand() / (RAND_MAX / (dest+1) + 1) + + //positions from 0 to dest + src = rand() / (RAND_MAX / (dest+1) + 1); + + //swap the cards + temp = cardlist[src]; + cardlist[src] = cardlist[dest]; + cardlist[dest] = temp; + } +} + +void CardStack::Reverse() +{ + for(int i = 0; i < nNumCards / 2; i++) + { + Card temp = cardlist[i]; + cardlist[i] = cardlist[nNumCards - i - 1]; + cardlist[nNumCards - i - 1] = temp; + } +} + +void CardStack::Push(const Card card) +{ + if(nNumCards < MAX_CARDSTACK_SIZE) + cardlist[nNumCards++] = card; +} + +void CardStack::Push(const CardStack &cardstack) +{ + if(nNumCards + cardstack.nNumCards < MAX_CARDSTACK_SIZE) + { + int num = cardstack.NumCards(); + + for(int i = 0; i < num; i++) + cardlist[nNumCards++] = cardstack.cardlist[i]; + } +} + +CardStack& CardStack::operator += (Card card) +{ + Push(card); + return *this; +} + +CardStack& CardStack::operator += (CardStack &cs) +{ + Push(cs); + return *this; +} + +CardStack CardStack::operator + (Card card) +{ + CardStack poo = *this; + poo.Push(card); + return poo; +} + +CardStack CardStack::operator + (CardStack &cs) +{ + CardStack poo = *this; + poo.Push(cs); + return poo; +} + + +Card CardStack::Pop() +{ + if(nNumCards > 0) + return cardlist[--nNumCards]; + else + return 0; +} + +CardStack CardStack::Pop(int items) +{ + if(items <= nNumCards && nNumCards > 0) + { + CardStack cs(*this, nNumCards - items); + + nNumCards -= items; + + return cs; + } + else + { + return CardStack(); + } +} + +Card CardStack::Top() +{ + if(nNumCards > 0) + return cardlist[nNumCards - 1]; + else + return 0; +} + +CardStack CardStack::Top(int items) +{ + if(items <= nNumCards && nNumCards > 0) + { + return CardStack (*this, nNumCards - items); + } + else + { + return CardStack(); + } + +} + +Card CardStack::RemoveCard(size_t index) +{ + if(nNumCards == 0 || index >= (size_t)nNumCards) + return 0; + + //put index into reverse range.. + index = nNumCards - index - 1; + + Card temp = cardlist[index]; + + nNumCards--; + + for(size_t i = index; i < (size_t)nNumCards; i++) + { + cardlist[i] = cardlist[i+1]; + } + + return temp; +} + +void CardStack::InsertCard(size_t index, Card card) +{ + if(nNumCards == MAX_CARDSTACK_SIZE) + return; + + if(index > (size_t)nNumCards) + return; + + if((size_t)nNumCards == index) + { + cardlist[nNumCards] = card; + nNumCards++; + return; + } + + //put index into reverse range.. + index = nNumCards - index - 1; + + nNumCards++; + + //make room for the card + for(size_t i = nNumCards; i > index; i--) + { + cardlist[i] = cardlist[i - 1]; + } + + cardlist[index] = card; +} + + +void CardStack::Print() +{ +// for(int i = 0; i < nNumCards; i++) +// cout << cardlist[i].HiVal() << " "; +} + +CardStack::CardStack(CardStack ©this, size_t fromindex) +{ + nNumCards = copythis.nNumCards - fromindex; + + for(int i = 0; i < nNumCards; i++) + cardlist[i] = copythis.cardlist[fromindex + i]; +} + diff --git a/rosapps/games/solitaire/cardlib/cardstack.h b/rosapps/games/solitaire/cardlib/cardstack.h index eae8736157b..03d98f1415f 100644 --- a/rosapps/games/solitaire/cardlib/cardstack.h +++ b/rosapps/games/solitaire/cardlib/cardstack.h @@ -1,53 +1,53 @@ -#ifndef CARDSTACK_INCLUDED -#define CARDSTACK_INCLUDED - -#include "card.h" - -#define MAX_CARDSTACK_SIZE 128 - -class CardStack -{ - friend class CardRegion; - -public: - CardStack() : nNumCards(0) { } - - void NewDeck(); - int NumCards() const { return nNumCards; } - void Shuffle(); - void Clear(); - void Reverse(); - - void Push(const Card card); - void Push(const CardStack &cardstack); - - Card Pop(); - CardStack Pop(int items); - - Card Top(); - CardStack Top(int items); - - void Print(); - - Card RemoveCard(size_t index); - void InsertCard(size_t index, Card card); - - //subscript capability!! - Card & operator[] (size_t index); - const Card & operator[] (size_t index) const; - - CardStack &operator += (Card card); - CardStack &operator += (CardStack &cs); - - CardStack operator + (Card card); - CardStack operator + (CardStack &cs); - -private: - - CardStack(CardStack ©this, size_t fromindex); - - Card cardlist[MAX_CARDSTACK_SIZE]; - int nNumCards; -}; - -#endif +#ifndef CARDSTACK_INCLUDED +#define CARDSTACK_INCLUDED + +#include "card.h" + +#define MAX_CARDSTACK_SIZE 128 + +class CardStack +{ + friend class CardRegion; + +public: + CardStack() : nNumCards(0) { } + + void NewDeck(); + int NumCards() const { return nNumCards; } + void Shuffle(); + void Clear(); + void Reverse(); + + void Push(const Card card); + void Push(const CardStack &cardstack); + + Card Pop(); + CardStack Pop(int items); + + Card Top(); + CardStack Top(int items); + + void Print(); + + Card RemoveCard(size_t index); + void InsertCard(size_t index, Card card); + + //subscript capability!! + Card & operator[] (size_t index); + const Card & operator[] (size_t index) const; + + CardStack &operator += (Card card); + CardStack &operator += (CardStack &cs); + + CardStack operator + (Card card); + CardStack operator + (CardStack &cs); + +private: + + CardStack(CardStack ©this, size_t fromindex); + + Card cardlist[MAX_CARDSTACK_SIZE]; + int nNumCards; +}; + +#endif diff --git a/rosapps/games/solitaire/cardlib/cardwindow.cpp b/rosapps/games/solitaire/cardlib/cardwindow.cpp index 44550867509..1eea0bffb90 100644 --- a/rosapps/games/solitaire/cardlib/cardwindow.cpp +++ b/rosapps/games/solitaire/cardlib/cardwindow.cpp @@ -1,811 +1,811 @@ -// -// CardLib - CardWindow class -// -// Freeware -// Copyright J Brown 2001 -// -#include -#include - -#include "globals.h" -#include "cardlib.h" -#include "cardbutton.h" -#include "cardregion.h" -#include "cardwindow.h" -#include "cardcolor.h" - -extern HPALETTE __holdplacepal; - -HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette) -{ - HPALETTE hOld; - - hOld = SelectPalette(hdc, hPalette, FALSE); - RealizePalette(hdc); - - return hOld; -} - -void RestorePalette(HDC hdc, HPALETTE hOldPal) -{ - SelectPalette(hdc, hOldPal, TRUE); -} - -HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours); -void PaintRect(HDC hdc, RECT *rect, COLORREF colour); -HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height); -void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2); - -void LoadCardBitmaps(); -void FreeCardBitmaps(); - -static TCHAR szCardName[] = _T("CardWnd32"); -static bool fRegistered = false; -static LONG uCardBitmapRef = 0; - - -void RegisterCardWindow() -{ - WNDCLASSEX wc; - - //Window class for the main application parent window - wc.cbSize = sizeof(wc); - wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW; - wc.lpfnWndProc = CardWindow::CardWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = sizeof(CardWindow *); - wc.hInstance = GetModuleHandle(0); - wc.hIcon = 0; - wc.hCursor = LoadCursor (NULL, IDC_ARROW); - wc.hbrBackground = 0; - wc.lpszMenuName = 0; - wc.lpszClassName = szCardName; - wc.hIconSm = 0; - - RegisterClassEx(&wc); -} - -CardWindow::CardWindow() : m_hWnd(0) -{ - HDC hdc = GetDC(0); - - nNumButtons = 0; - nNumCardRegions = 0; - nNumDropZones = 0; - nBackCardIdx = 53; - - ResizeWndCallback = 0; - hbmBackImage = 0; - hdcBackImage = 0; - - srand((unsigned)GetTickCount()); - - //All colours (buttons, highlights, decks) - //are calculated off this single base colour - crBackgnd = PALETTERGB(0,80,0);//PALETTERGB(0,64,100); - - // If uCardBitmapRef was previously zero, then - // load the card bitmaps - if(1 == InterlockedIncrement(&uCardBitmapRef)) - { - LoadCardBitmaps(); - - __hPalette = CreateCardPalette(); - - __hdcPlaceHolder = CreateCompatibleDC(hdc); - - __holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette); - - __hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight); - - } - - ReleaseDC(0, hdc); - - //register the window class if necessary - if(!fRegistered) - { - fRegistered = true; - RegisterCardWindow(); - } - -} - -BOOL CardWindow::Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height) -{ - if(m_hWnd) - return FALSE; - - //Create the window associated with this object - m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, szCardName, 0, - WS_CHILD | WS_VISIBLE, - 0,0,100,100, - hwndParent, 0, GetModuleHandle(0), this); - - return TRUE; -} - -BOOL CardWindow::Destroy() -{ - DestroyWindow(m_hWnd); - m_hWnd = 0; - - return TRUE; -} - -CardWindow::~CardWindow() -{ - if(m_hWnd) - DestroyWindow(m_hWnd); - - DeleteAll(); - - if(0 == InterlockedDecrement(&uCardBitmapRef)) - { - FreeCardBitmaps(); - - DeleteObject(__hbmPlaceHolder); - DeleteDC (__hdcPlaceHolder); - - RestorePalette(__hdcPlaceHolder, __holdplacepal); - - if(__hPalette) - DeleteObject(__hPalette); - } -} - -bool CardWindow::DeleteAll() -{ - int i; - - for(i = 0; i < nNumCardRegions; i++) - { - delete Regions[i]; - } - - for(i = 0; i < nNumButtons; i++) - { - delete Buttons[i]; - } - - for(i = 0; i < nNumDropZones; i++) - { - delete dropzone[i]; - } - - nNumCardRegions = nNumButtons = nNumDropZones = 0; - - return true; -} - -void CardWindow::SetBackColor(COLORREF cr) -{ - crBackgnd = cr; - int i; - - // - // Create the exact palette we need to render the buttons/stacks - // - RestorePalette(__hdcPlaceHolder, __holdplacepal); - - if(__hPalette) - DeleteObject(__hPalette); - - __hPalette = CreateCardPalette(); - - // - // re-create the place-holder! - HDC hdc = GetDC(m_hWnd); - - DeleteObject(__hbmPlaceHolder); - - __holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette); - - __hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight); - //SelectObject(__hdcPlaceHolder, __hbmPlaceHolder); - - //reset all buttons to same colour - for(i = 0; i < nNumButtons; i++) - { - if(Buttons[i]->GetStyle() & CB_PUSHBUTTON) - { - Buttons[i]->SetBackColor(ColorScaleRGB(crBackgnd, RGB(255,255,255), 0.1)); - } - else - { - Buttons[i]->SetBackColor(crBackgnd); - } - } - - for(i = 0; i < nNumCardRegions; i++) - { - Regions[i]->SetBackColor(crBackgnd); - } - - - ReleaseDC(m_hWnd, hdc); -} - -COLORREF CardWindow::GetBackColor() -{ - return crBackgnd; -} - -CardButton* CardWindow::CardButtonFromPoint(int x, int y) -{ - CardButton *bptr = 0; - - POINT pt; - pt.x = x; - pt.y = y; - - //Search BACKWARDS...to reflect the implicit Z-order that - //the button creation provided - for(int i = nNumButtons - 1; i >= 0; i--) - { - bptr = Buttons[i]; - if(PtInRect(&bptr->rect, pt) && bptr->fVisible) - return bptr; - } - - return 0; -} - -CardRegion* CardWindow::CardRegionFromPoint(int x, int y) -{ - POINT pt; - pt.x = x; - pt.y = y; - - //Search BACKWARDS...to reflect the implicit Z-order that - //the stack creation provided - for(int i = nNumCardRegions - 1; i >= 0; i--) - { - if(Regions[i]->IsPointInStack(x, y)) - return Regions[i]; - } - - return 0; -} - -// -// Forward all window messages onto the appropriate -// class instance -// -LRESULT CALLBACK CardWindow::CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) -{ - CardWindow *cw = (CardWindow *)GetWindowLong(hwnd, 0); - return cw->WndProc(hwnd, iMsg, wParam, lParam); -} - -void CardWindow::Paint(HDC hdc) -{ - int i; - RECT rect; - HPALETTE hOldPal; - - hOldPal = UseNicePalette(hdc, __hPalette); - - // - // Clip the card stacks so that they won't - // get painted over - // - for(i = 0; i < nNumCardRegions; i++) - { - Regions[i]->Clip(hdc); - } - - // - // Clip the buttons - // - for(i = 0; i < nNumButtons; i++) - { - Buttons[i]->Clip(hdc); - } - - - // Now paint the whole screen with background colour, - // - GetClientRect(m_hWnd, &rect); - - //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd)); - PaintCardRgn(hdc, 0, 0, rect.right, rect.bottom, 0, 0); - SelectClipRgn(hdc, NULL); - - // Don't let cards draw over buttons, so clip buttons again - // - for(i = 0; i < nNumButtons; i++) - { - Buttons[i]->Clip(hdc); - } - - // Paint each card stack in turn - // - for(i = 0; i < nNumCardRegions; i++) - { - Regions[i]->Render(hdc); - } - - // Paint each button now - // - SelectClipRgn(hdc, NULL); - - for(i = 0; i < nNumButtons; i++) - { - Buttons[i]->Redraw(); - } - - RestorePalette(hdc, hOldPal); -} - - - - -LRESULT CALLBACK CardWindow::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) -{ - HDC hdc; - PAINTSTRUCT ps; - - CREATESTRUCT *cs; - - static CardButton *buttonptr = 0; - static CardRegion *stackptr = 0; - - int x, y, i; - - switch(iMsg) - { - case WM_NCCREATE: - - // When we created this window, we passed in the - // pointer to the class object (CardWindow *) in the - // call to CreateWindow. - cs = (CREATESTRUCT *)lParam; - - // - // associate this class with the window - // - SetWindowLong(hwnd, 0, (LONG)cs->lpCreateParams); - - return 1; - - case WM_NCDESTROY: - // Don't delete anything here.. - break; - - case WM_SIZE: - nWidth = LOWORD(lParam); - nHeight = HIWORD(lParam); - - // - // reposition all the stacks and buttons - // in case any of them are centered, right-justified etc - // - for(i = 0; i < nNumCardRegions; i++) - { - Regions[i]->AdjustPosition(nWidth, nHeight); - } - - for(i = 0; i < nNumButtons; i++) - { - Buttons[i]->AdjustPosition(nWidth, nHeight); - } - - // - // Call the user-defined resize proc AFTER all the stacks - // have been positioned - // - if(ResizeWndCallback) - ResizeWndCallback(nWidth, nHeight); - - return 0; - - case WM_PAINT: - - hdc = BeginPaint(hwnd, &ps); - - Paint(hdc); - - EndPaint(hwnd, &ps); - return 0; - - case WM_TIMER: - - //find the timer object in the registered funcs - /*if(wParam >= 0x10000) - { - for(i = 0; i < nRegFuncs; i++) - { - if(RegFuncs[i].id == wParam) - { - KillTimer(hwnd, wParam); - - //call the registered function!! - RegFuncs[i].func(RegFuncs[i].dwParam); - - RegFuncs[i] = RegFuncs[nRegFuncs-1]; - nRegFuncs--; - } - } - } - else*/ - { - //find the cardstack - CardRegion *stackobj = (CardRegion *)wParam;//CardStackFromId(wParam); - stackobj->DoFlash(); - } - - return 0; - - case WM_LBUTTONDBLCLK: - - x = (short)LOWORD(lParam); - y = (short)HIWORD(lParam); - - if((buttonptr = CardButtonFromPoint(x, y)) != 0) - { - buttonptr->OnLButtonDown(hwnd, x, y); - return 0; - } - - if((stackptr = CardRegionFromPoint(x, y)) != 0) - { - stackptr->OnLButtonDblClk(x, y); - stackptr = 0; - } - - return 0; - - case WM_LBUTTONDOWN: - - x = (short)LOWORD(lParam); - y = (short)HIWORD(lParam); - - //if clicked on a button - if((buttonptr = CardButtonFromPoint(x, y)) != 0) - { - if(buttonptr->OnLButtonDown(hwnd, x, y) == 0) - buttonptr = 0; - - return 0; - } - - if((stackptr = CardRegionFromPoint(x, y)) != 0) - { - if(!stackptr->OnLButtonDown(x, y)) - stackptr = 0; - } - - return 0; - - case WM_LBUTTONUP: - - x = (short)LOWORD(lParam); - y = (short)HIWORD(lParam); - - // - // if we were clicking a button - // - if(buttonptr != 0) - { - buttonptr->OnLButtonUp(hwnd, x, y); - buttonptr = 0; - return 0; - } - - if(stackptr != 0) - { - stackptr->OnLButtonUp(x, y); - stackptr = 0; - return 0; - } - - return 0; - - case WM_MOUSEMOVE: - - x = (short)LOWORD(lParam); - y = (short)HIWORD(lParam); - - // if we were clicking a button - if(buttonptr != 0) - { - buttonptr->OnMouseMove(hwnd, x, y); - return 0; - } - - if(stackptr != 0) - { - return stackptr->OnMouseMove(x, y); - } - - return 0; - - } - - return DefWindowProc (hwnd, iMsg, wParam, lParam); -} - - -CardRegion* CardWindow::CardRegionFromId(int id) -{ - for(int i = 0; i < nNumCardRegions; i++) - { - if(Regions[i]->id == id) - return Regions[i]; - } - - return 0; -} - -CardButton* CardWindow::CardButtonFromId(int id) -{ - for(int i = 0; i < nNumButtons; i++) - { - if(Buttons[i]->id == id) - return Buttons[i]; - } - - return 0; -} - -void CardWindow::Redraw() -{ - InvalidateRect(m_hWnd, 0, 0); - UpdateWindow(m_hWnd); -} - -bool CardWindow::DeleteButton(CardButton *pButton) -{ - for(int i = 0; i < nNumButtons; i++) - { - if(Buttons[i] == pButton) - { - CardButton *cb = Buttons[i]; - - //shift any after this one backwards - for(int j = i; j < nNumButtons - 1; j++) - { - Buttons[j] = Buttons[j + 1]; - } - - delete cb; - nNumButtons--; - - return true; - } - } - - return false; -} - -bool CardWindow::DeleteRegion(CardRegion *pRegion) -{ - for(int i = 0; i < nNumCardRegions; i++) - { - if(Regions[i] == pRegion) - { - CardRegion *cr = Regions[i]; - - //shift any after this one backwards - for(int j = i; j < nNumCardRegions - 1; j++) - { - Regions[j] = Regions[j + 1]; - } - - delete cr; - nNumCardRegions--; - - return true; - } - } - - return false; -} - -void CardWindow::EmptyStacks(void) -{ - for(int i = 0; i < nNumCardRegions; i++) - { - Regions[i]->Clear(); - Regions[i]->Update(); - } - - Redraw(); -} - -bool CardWindow::DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX) -{ - int numvisiblestacks = 0; - int curx = nStartX; - int startindex = -1; - int i; - - //find the stack which starts with our ID - for(i = 0; i < nNumCardRegions; i++) - { - if(Regions[i]->Id() == nIdFrom) - { - startindex = i; - break; - } - } - - //if didn't find, return - if(i == nNumCardRegions) return false; - - //count the stacks that are visible - for(i = startindex; i < startindex + nNumStacks; i++) - { - if(Regions[i]->IsVisible()) - numvisiblestacks++; - } - - if(xJustify == CS_XJUST_CENTER) - { - //startx -= ((numvisiblestacks + spacing) * cardwidth - spacing) / 2; - int viswidth; - viswidth = numvisiblestacks * __cardwidth; - viswidth += xSpacing * (numvisiblestacks - 1); - curx = -(viswidth - __cardwidth) / 2; - - for(i = startindex; i < startindex + nNumStacks; i++) - { - if(Regions[i]->IsVisible()) - { - Regions[i]->xadjust = curx; - Regions[i]->xjustify = CS_XJUST_CENTER; - curx += Regions[i]->width + xSpacing; - } - - } - } - - if(xJustify == CS_XJUST_RIGHT) - { - nStartX -= ((numvisiblestacks + xSpacing) * __cardwidth - xSpacing); - } - - if(xJustify == CS_XJUST_NONE) - { - for(i = startindex; i < startindex + nNumStacks; i++) - { - if(Regions[i]->IsVisible()) - { - Regions[i]->xpos = curx; - curx += Regions[i]->width + xSpacing; - Regions[i]->UpdateSize(); - } - - } - } - - return 0; -} - -void CardWindow::Update() -{ - for(int i = 0; i < nNumCardRegions; i++) - { - Regions[i]->AdjustPosition(nWidth, nHeight); - } -} - - -void CardWindow::SetResizeProc(pResizeWndProc proc) -{ - ResizeWndCallback = proc; -} - - -HPALETTE CardWindow::CreateCardPalette() -{ - COLORREF cols[10]; - int nNumCols; - - - //include button text colours - cols[0] = RGB(0, 0, 0); - cols[1] = RGB(255, 255, 255); - - //include the base background colour - cols[1] = crBackgnd; - - //include the standard button colours... - cols[3] = CardButton::GetHighlight(crBackgnd); - cols[4] = CardButton::GetShadow(crBackgnd); - cols[5] = CardButton::GetFace(crBackgnd); - - //include the sunken image bitmap colours... - GetSinkCols(crBackgnd, &cols[6], &cols[7], &cols[8], &cols[9]); - - nNumCols = 10; - - return MakePaletteFromCols(cols, nNumCols); -} - -void CardWindow::SetBackCardIdx(UINT uBackIdx) -{ - if(uBackIdx >= 52 && uBackIdx <= 68) - nBackCardIdx = uBackIdx; - - for(int i = 0; i < nNumCardRegions; i++) - Regions[i]->SetBackCardIdx(uBackIdx); - -} - -void CardWindow::PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy) -{ - RECT rect; - - //if just a solid background colour - if(hbmBackImage == 0) - { - SetRect(&rect, dx, dy, dx+width, dy+height); - - /*if(GetVersion() < 0x80000000) - { - PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd)); - } - else*/ - { - HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBackgnd)); - FillRect(hdc, &rect, hbr); - DeleteObject(hbr); - } - } - //otherwise, paint using the bitmap - else - { - // Draw whatever part of background we can - BitBlt(hdc, dx, dy, width, height, hdcBackImage, sx, sy, SRCCOPY); - - // Now we need to paint any area outside the bitmap, - // just in case the bitmap is too small to fill whole window - if(0)//sx + width > bm.bmWidth || sy + height > bm.bmHeight) - { - // Find out size of bitmap - BITMAP bm; - GetObject(hbmBackImage, sizeof(bm), &bm); - - HRGN hr1 = CreateRectRgn(sx, sy, sx+width, sy+height); - HRGN hr2 = CreateRectRgn(0, 0, bm.bmWidth, bm.bmHeight); - HRGN hr3 = CreateRectRgn(0,0, 1, 1); - HRGN hr4 = CreateRectRgn(0,0, 1, 1); - - CombineRgn(hr3, hr1, hr2, RGN_DIFF); - - GetClipRgn(hdc, hr4); - - CombineRgn(hr3, hr4, hr3, RGN_AND); - SelectClipRgn(hdc, hr3); - - // Fill remaining space not filled with bitmap - HBRUSH hbr = CreateSolidBrush(crBackgnd); - FillRgn(hdc, hr3, hbr); - DeleteObject(hbr); - - // Clean up - SelectClipRgn(hdc, hr4); - - DeleteObject(hr1); - DeleteObject(hr2); - DeleteObject(hr3); - DeleteObject(hr4); - } - } -} - -void CardWindow::SetBackImage(HBITMAP hBitmap) -{ - //delete current image?? NO! - if(hdcBackImage == 0) - { - hdcBackImage = CreateCompatibleDC(0); - } - - hbmBackImage = hBitmap; - - if(hBitmap) - SelectObject(hdcBackImage, hBitmap); -} +// +// CardLib - CardWindow class +// +// Freeware +// Copyright J Brown 2001 +// +#include +#include + +#include "globals.h" +#include "cardlib.h" +#include "cardbutton.h" +#include "cardregion.h" +#include "cardwindow.h" +#include "cardcolor.h" + +extern HPALETTE __holdplacepal; + +HPALETTE UseNicePalette(HDC hdc, HPALETTE hPalette) +{ + HPALETTE hOld; + + hOld = SelectPalette(hdc, hPalette, FALSE); + RealizePalette(hdc); + + return hOld; +} + +void RestorePalette(HDC hdc, HPALETTE hOldPal) +{ + SelectPalette(hdc, hOldPal, TRUE); +} + +HPALETTE MakePaletteFromCols(COLORREF cols[], int nNumColours); +void PaintRect(HDC hdc, RECT *rect, COLORREF colour); +HBITMAP CreateSinkBmp(HDC hdcCompat, HDC hdc, COLORREF col, int width, int height); +void GetSinkCols(COLORREF crBase, COLORREF *fg, COLORREF *bg, COLORREF *sh1, COLORREF *sh2); + +void LoadCardBitmaps(); +void FreeCardBitmaps(); + +static TCHAR szCardName[] = _T("CardWnd32"); +static bool fRegistered = false; +static LONG uCardBitmapRef = 0; + + +void RegisterCardWindow() +{ + WNDCLASSEX wc; + + //Window class for the main application parent window + wc.cbSize = sizeof(wc); + wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW; + wc.lpfnWndProc = CardWindow::CardWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(CardWindow *); + wc.hInstance = GetModuleHandle(0); + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.hbrBackground = 0; + wc.lpszMenuName = 0; + wc.lpszClassName = szCardName; + wc.hIconSm = 0; + + RegisterClassEx(&wc); +} + +CardWindow::CardWindow() : m_hWnd(0) +{ + HDC hdc = GetDC(0); + + nNumButtons = 0; + nNumCardRegions = 0; + nNumDropZones = 0; + nBackCardIdx = 53; + + ResizeWndCallback = 0; + hbmBackImage = 0; + hdcBackImage = 0; + + srand((unsigned)GetTickCount()); + + //All colours (buttons, highlights, decks) + //are calculated off this single base colour + crBackgnd = PALETTERGB(0,80,0);//PALETTERGB(0,64,100); + + // If uCardBitmapRef was previously zero, then + // load the card bitmaps + if(1 == InterlockedIncrement(&uCardBitmapRef)) + { + LoadCardBitmaps(); + + __hPalette = CreateCardPalette(); + + __hdcPlaceHolder = CreateCompatibleDC(hdc); + + __holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette); + + __hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight); + + } + + ReleaseDC(0, hdc); + + //register the window class if necessary + if(!fRegistered) + { + fRegistered = true; + RegisterCardWindow(); + } + +} + +BOOL CardWindow::Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height) +{ + if(m_hWnd) + return FALSE; + + //Create the window associated with this object + m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, szCardName, 0, + WS_CHILD | WS_VISIBLE, + 0,0,100,100, + hwndParent, 0, GetModuleHandle(0), this); + + return TRUE; +} + +BOOL CardWindow::Destroy() +{ + DestroyWindow(m_hWnd); + m_hWnd = 0; + + return TRUE; +} + +CardWindow::~CardWindow() +{ + if(m_hWnd) + DestroyWindow(m_hWnd); + + DeleteAll(); + + if(0 == InterlockedDecrement(&uCardBitmapRef)) + { + FreeCardBitmaps(); + + DeleteObject(__hbmPlaceHolder); + DeleteDC (__hdcPlaceHolder); + + RestorePalette(__hdcPlaceHolder, __holdplacepal); + + if(__hPalette) + DeleteObject(__hPalette); + } +} + +bool CardWindow::DeleteAll() +{ + int i; + + for(i = 0; i < nNumCardRegions; i++) + { + delete Regions[i]; + } + + for(i = 0; i < nNumButtons; i++) + { + delete Buttons[i]; + } + + for(i = 0; i < nNumDropZones; i++) + { + delete dropzone[i]; + } + + nNumCardRegions = nNumButtons = nNumDropZones = 0; + + return true; +} + +void CardWindow::SetBackColor(COLORREF cr) +{ + crBackgnd = cr; + int i; + + // + // Create the exact palette we need to render the buttons/stacks + // + RestorePalette(__hdcPlaceHolder, __holdplacepal); + + if(__hPalette) + DeleteObject(__hPalette); + + __hPalette = CreateCardPalette(); + + // + // re-create the place-holder! + HDC hdc = GetDC(m_hWnd); + + DeleteObject(__hbmPlaceHolder); + + __holdplacepal = UseNicePalette(__hdcPlaceHolder, __hPalette); + + __hbmPlaceHolder = CreateSinkBmp(hdc, __hdcPlaceHolder, crBackgnd, __cardwidth, __cardheight); + //SelectObject(__hdcPlaceHolder, __hbmPlaceHolder); + + //reset all buttons to same colour + for(i = 0; i < nNumButtons; i++) + { + if(Buttons[i]->GetStyle() & CB_PUSHBUTTON) + { + Buttons[i]->SetBackColor(ColorScaleRGB(crBackgnd, RGB(255,255,255), 0.1)); + } + else + { + Buttons[i]->SetBackColor(crBackgnd); + } + } + + for(i = 0; i < nNumCardRegions; i++) + { + Regions[i]->SetBackColor(crBackgnd); + } + + + ReleaseDC(m_hWnd, hdc); +} + +COLORREF CardWindow::GetBackColor() +{ + return crBackgnd; +} + +CardButton* CardWindow::CardButtonFromPoint(int x, int y) +{ + CardButton *bptr = 0; + + POINT pt; + pt.x = x; + pt.y = y; + + //Search BACKWARDS...to reflect the implicit Z-order that + //the button creation provided + for(int i = nNumButtons - 1; i >= 0; i--) + { + bptr = Buttons[i]; + if(PtInRect(&bptr->rect, pt) && bptr->fVisible) + return bptr; + } + + return 0; +} + +CardRegion* CardWindow::CardRegionFromPoint(int x, int y) +{ + POINT pt; + pt.x = x; + pt.y = y; + + //Search BACKWARDS...to reflect the implicit Z-order that + //the stack creation provided + for(int i = nNumCardRegions - 1; i >= 0; i--) + { + if(Regions[i]->IsPointInStack(x, y)) + return Regions[i]; + } + + return 0; +} + +// +// Forward all window messages onto the appropriate +// class instance +// +LRESULT CALLBACK CardWindow::CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + CardWindow *cw = (CardWindow *)GetWindowLong(hwnd, 0); + return cw->WndProc(hwnd, iMsg, wParam, lParam); +} + +void CardWindow::Paint(HDC hdc) +{ + int i; + RECT rect; + HPALETTE hOldPal; + + hOldPal = UseNicePalette(hdc, __hPalette); + + // + // Clip the card stacks so that they won't + // get painted over + // + for(i = 0; i < nNumCardRegions; i++) + { + Regions[i]->Clip(hdc); + } + + // + // Clip the buttons + // + for(i = 0; i < nNumButtons; i++) + { + Buttons[i]->Clip(hdc); + } + + + // Now paint the whole screen with background colour, + // + GetClientRect(m_hWnd, &rect); + + //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd)); + PaintCardRgn(hdc, 0, 0, rect.right, rect.bottom, 0, 0); + SelectClipRgn(hdc, NULL); + + // Don't let cards draw over buttons, so clip buttons again + // + for(i = 0; i < nNumButtons; i++) + { + Buttons[i]->Clip(hdc); + } + + // Paint each card stack in turn + // + for(i = 0; i < nNumCardRegions; i++) + { + Regions[i]->Render(hdc); + } + + // Paint each button now + // + SelectClipRgn(hdc, NULL); + + for(i = 0; i < nNumButtons; i++) + { + Buttons[i]->Redraw(); + } + + RestorePalette(hdc, hOldPal); +} + + + + +LRESULT CALLBACK CardWindow::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + HDC hdc; + PAINTSTRUCT ps; + + CREATESTRUCT *cs; + + static CardButton *buttonptr = 0; + static CardRegion *stackptr = 0; + + int x, y, i; + + switch(iMsg) + { + case WM_NCCREATE: + + // When we created this window, we passed in the + // pointer to the class object (CardWindow *) in the + // call to CreateWindow. + cs = (CREATESTRUCT *)lParam; + + // + // associate this class with the window + // + SetWindowLong(hwnd, 0, (LONG)cs->lpCreateParams); + + return 1; + + case WM_NCDESTROY: + // Don't delete anything here.. + break; + + case WM_SIZE: + nWidth = LOWORD(lParam); + nHeight = HIWORD(lParam); + + // + // reposition all the stacks and buttons + // in case any of them are centered, right-justified etc + // + for(i = 0; i < nNumCardRegions; i++) + { + Regions[i]->AdjustPosition(nWidth, nHeight); + } + + for(i = 0; i < nNumButtons; i++) + { + Buttons[i]->AdjustPosition(nWidth, nHeight); + } + + // + // Call the user-defined resize proc AFTER all the stacks + // have been positioned + // + if(ResizeWndCallback) + ResizeWndCallback(nWidth, nHeight); + + return 0; + + case WM_PAINT: + + hdc = BeginPaint(hwnd, &ps); + + Paint(hdc); + + EndPaint(hwnd, &ps); + return 0; + + case WM_TIMER: + + //find the timer object in the registered funcs + /*if(wParam >= 0x10000) + { + for(i = 0; i < nRegFuncs; i++) + { + if(RegFuncs[i].id == wParam) + { + KillTimer(hwnd, wParam); + + //call the registered function!! + RegFuncs[i].func(RegFuncs[i].dwParam); + + RegFuncs[i] = RegFuncs[nRegFuncs-1]; + nRegFuncs--; + } + } + } + else*/ + { + //find the cardstack + CardRegion *stackobj = (CardRegion *)wParam;//CardStackFromId(wParam); + stackobj->DoFlash(); + } + + return 0; + + case WM_LBUTTONDBLCLK: + + x = (short)LOWORD(lParam); + y = (short)HIWORD(lParam); + + if((buttonptr = CardButtonFromPoint(x, y)) != 0) + { + buttonptr->OnLButtonDown(hwnd, x, y); + return 0; + } + + if((stackptr = CardRegionFromPoint(x, y)) != 0) + { + stackptr->OnLButtonDblClk(x, y); + stackptr = 0; + } + + return 0; + + case WM_LBUTTONDOWN: + + x = (short)LOWORD(lParam); + y = (short)HIWORD(lParam); + + //if clicked on a button + if((buttonptr = CardButtonFromPoint(x, y)) != 0) + { + if(buttonptr->OnLButtonDown(hwnd, x, y) == 0) + buttonptr = 0; + + return 0; + } + + if((stackptr = CardRegionFromPoint(x, y)) != 0) + { + if(!stackptr->OnLButtonDown(x, y)) + stackptr = 0; + } + + return 0; + + case WM_LBUTTONUP: + + x = (short)LOWORD(lParam); + y = (short)HIWORD(lParam); + + // + // if we were clicking a button + // + if(buttonptr != 0) + { + buttonptr->OnLButtonUp(hwnd, x, y); + buttonptr = 0; + return 0; + } + + if(stackptr != 0) + { + stackptr->OnLButtonUp(x, y); + stackptr = 0; + return 0; + } + + return 0; + + case WM_MOUSEMOVE: + + x = (short)LOWORD(lParam); + y = (short)HIWORD(lParam); + + // if we were clicking a button + if(buttonptr != 0) + { + buttonptr->OnMouseMove(hwnd, x, y); + return 0; + } + + if(stackptr != 0) + { + return stackptr->OnMouseMove(x, y); + } + + return 0; + + } + + return DefWindowProc (hwnd, iMsg, wParam, lParam); +} + + +CardRegion* CardWindow::CardRegionFromId(int id) +{ + for(int i = 0; i < nNumCardRegions; i++) + { + if(Regions[i]->id == id) + return Regions[i]; + } + + return 0; +} + +CardButton* CardWindow::CardButtonFromId(int id) +{ + for(int i = 0; i < nNumButtons; i++) + { + if(Buttons[i]->id == id) + return Buttons[i]; + } + + return 0; +} + +void CardWindow::Redraw() +{ + InvalidateRect(m_hWnd, 0, 0); + UpdateWindow(m_hWnd); +} + +bool CardWindow::DeleteButton(CardButton *pButton) +{ + for(int i = 0; i < nNumButtons; i++) + { + if(Buttons[i] == pButton) + { + CardButton *cb = Buttons[i]; + + //shift any after this one backwards + for(int j = i; j < nNumButtons - 1; j++) + { + Buttons[j] = Buttons[j + 1]; + } + + delete cb; + nNumButtons--; + + return true; + } + } + + return false; +} + +bool CardWindow::DeleteRegion(CardRegion *pRegion) +{ + for(int i = 0; i < nNumCardRegions; i++) + { + if(Regions[i] == pRegion) + { + CardRegion *cr = Regions[i]; + + //shift any after this one backwards + for(int j = i; j < nNumCardRegions - 1; j++) + { + Regions[j] = Regions[j + 1]; + } + + delete cr; + nNumCardRegions--; + + return true; + } + } + + return false; +} + +void CardWindow::EmptyStacks(void) +{ + for(int i = 0; i < nNumCardRegions; i++) + { + Regions[i]->Clear(); + Regions[i]->Update(); + } + + Redraw(); +} + +bool CardWindow::DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX) +{ + int numvisiblestacks = 0; + int curx = nStartX; + int startindex = -1; + int i; + + //find the stack which starts with our ID + for(i = 0; i < nNumCardRegions; i++) + { + if(Regions[i]->Id() == nIdFrom) + { + startindex = i; + break; + } + } + + //if didn't find, return + if(i == nNumCardRegions) return false; + + //count the stacks that are visible + for(i = startindex; i < startindex + nNumStacks; i++) + { + if(Regions[i]->IsVisible()) + numvisiblestacks++; + } + + if(xJustify == CS_XJUST_CENTER) + { + //startx -= ((numvisiblestacks + spacing) * cardwidth - spacing) / 2; + int viswidth; + viswidth = numvisiblestacks * __cardwidth; + viswidth += xSpacing * (numvisiblestacks - 1); + curx = -(viswidth - __cardwidth) / 2; + + for(i = startindex; i < startindex + nNumStacks; i++) + { + if(Regions[i]->IsVisible()) + { + Regions[i]->xadjust = curx; + Regions[i]->xjustify = CS_XJUST_CENTER; + curx += Regions[i]->width + xSpacing; + } + + } + } + + if(xJustify == CS_XJUST_RIGHT) + { + nStartX -= ((numvisiblestacks + xSpacing) * __cardwidth - xSpacing); + } + + if(xJustify == CS_XJUST_NONE) + { + for(i = startindex; i < startindex + nNumStacks; i++) + { + if(Regions[i]->IsVisible()) + { + Regions[i]->xpos = curx; + curx += Regions[i]->width + xSpacing; + Regions[i]->UpdateSize(); + } + + } + } + + return 0; +} + +void CardWindow::Update() +{ + for(int i = 0; i < nNumCardRegions; i++) + { + Regions[i]->AdjustPosition(nWidth, nHeight); + } +} + + +void CardWindow::SetResizeProc(pResizeWndProc proc) +{ + ResizeWndCallback = proc; +} + + +HPALETTE CardWindow::CreateCardPalette() +{ + COLORREF cols[10]; + int nNumCols; + + + //include button text colours + cols[0] = RGB(0, 0, 0); + cols[1] = RGB(255, 255, 255); + + //include the base background colour + cols[1] = crBackgnd; + + //include the standard button colours... + cols[3] = CardButton::GetHighlight(crBackgnd); + cols[4] = CardButton::GetShadow(crBackgnd); + cols[5] = CardButton::GetFace(crBackgnd); + + //include the sunken image bitmap colours... + GetSinkCols(crBackgnd, &cols[6], &cols[7], &cols[8], &cols[9]); + + nNumCols = 10; + + return MakePaletteFromCols(cols, nNumCols); +} + +void CardWindow::SetBackCardIdx(UINT uBackIdx) +{ + if(uBackIdx >= 52 && uBackIdx <= 68) + nBackCardIdx = uBackIdx; + + for(int i = 0; i < nNumCardRegions; i++) + Regions[i]->SetBackCardIdx(uBackIdx); + +} + +void CardWindow::PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy) +{ + RECT rect; + + //if just a solid background colour + if(hbmBackImage == 0) + { + SetRect(&rect, dx, dy, dx+width, dy+height); + + /*if(GetVersion() < 0x80000000) + { + PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd)); + } + else*/ + { + HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBackgnd)); + FillRect(hdc, &rect, hbr); + DeleteObject(hbr); + } + } + //otherwise, paint using the bitmap + else + { + // Draw whatever part of background we can + BitBlt(hdc, dx, dy, width, height, hdcBackImage, sx, sy, SRCCOPY); + + // Now we need to paint any area outside the bitmap, + // just in case the bitmap is too small to fill whole window + if(0)//sx + width > bm.bmWidth || sy + height > bm.bmHeight) + { + // Find out size of bitmap + BITMAP bm; + GetObject(hbmBackImage, sizeof(bm), &bm); + + HRGN hr1 = CreateRectRgn(sx, sy, sx+width, sy+height); + HRGN hr2 = CreateRectRgn(0, 0, bm.bmWidth, bm.bmHeight); + HRGN hr3 = CreateRectRgn(0,0, 1, 1); + HRGN hr4 = CreateRectRgn(0,0, 1, 1); + + CombineRgn(hr3, hr1, hr2, RGN_DIFF); + + GetClipRgn(hdc, hr4); + + CombineRgn(hr3, hr4, hr3, RGN_AND); + SelectClipRgn(hdc, hr3); + + // Fill remaining space not filled with bitmap + HBRUSH hbr = CreateSolidBrush(crBackgnd); + FillRgn(hdc, hr3, hbr); + DeleteObject(hbr); + + // Clean up + SelectClipRgn(hdc, hr4); + + DeleteObject(hr1); + DeleteObject(hr2); + DeleteObject(hr3); + DeleteObject(hr4); + } + } +} + +void CardWindow::SetBackImage(HBITMAP hBitmap) +{ + //delete current image?? NO! + if(hdcBackImage == 0) + { + hdcBackImage = CreateCompatibleDC(0); + } + + hbmBackImage = hBitmap; + + if(hBitmap) + SelectObject(hdcBackImage, hBitmap); +} diff --git a/rosapps/games/solitaire/cardlib/cardwindow.h b/rosapps/games/solitaire/cardlib/cardwindow.h index bcc24092e18..5a1b07a8430 100644 --- a/rosapps/games/solitaire/cardlib/cardwindow.h +++ b/rosapps/games/solitaire/cardlib/cardwindow.h @@ -1,119 +1,119 @@ -#ifndef CARDBOARD_INCLUDED -#define CARDBOARD_INCLUDED - -#define MAXBUTTONS 32 -#define MAXCARDSTACKS 32 -#define MAXDROPZONES 8 - -#include "dropzone.h" -#include "cardlib.h" - -class CardRegion; -class CardButton; - -LRESULT CALLBACK CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); - -class CardWindow -{ - friend class CardRegion; - friend class CardButton; - - friend void RegisterCardWindow(); - -public: - - CardWindow(); - ~CardWindow(); - - // - // Basic windowing support - // - BOOL Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height); - BOOL Destroy(); - - operator HWND() { return m_hWnd; } - - CardButton *CreateButton (int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height); - CardRegion *CreateRegion (int id, bool fVisible, int x, int y, int xoffset, int yoffset); - - CardButton *CardButtonFromId(int id); - CardRegion *CardRegionFromId(int id); - - bool DeleteButton(CardButton *pButton); - bool DeleteRegion(CardRegion *pRegion); - bool DeleteAll(); - - void SetBackColor(COLORREF cr); - COLORREF GetBackColor(); - void SetBackCardIdx(UINT uBackIdx); - void SetBackImage(HBITMAP hBitmap); - - void EmptyStacks(void); - void Redraw(void); - void Update(void); - - bool DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX); - void SetResizeProc(pResizeWndProc proc); - int GetWidth() { return nWidth; } - int GetHeight() { return nHeight; } - - // - // Dropzone support - // - bool RegisterDropZone(int id, RECT *rect, pDropZoneProc proc); - bool DeleteDropZone(int id); - -private: - - int GetNumDropZones() { return nNumDropZones; } - DropZone* GetDropZoneFromRect(RECT *rect); - - // - // Window procedure - don't call - // - LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); -static LRESULT CALLBACK CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); - - // - // Private functions - // - void Paint(HDC hdc); - void PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy); - - HPALETTE CreateCardPalette(); - - CardButton *CardButtonFromPoint(int x, int y); - CardRegion *CardRegionFromPoint(int x, int y); - CardRegion *GetBestStack(int x, int y, int w, int h); - - // - // Private members - // - - HWND m_hWnd; //window handle! - int nWidth, nHeight; - - UINT nBackCardIdx; //all stacks share this card index by default - - HBITMAP hbmBackImage; - HDC hdcBackImage; - - - CardButton * Buttons[MAXBUTTONS]; - int nNumButtons; - - CardRegion * Regions[MAXCARDSTACKS]; - int nNumCardRegions; - - DropZone * dropzone[MAXDROPZONES]; - int nNumDropZones; - - COLORREF crBackgnd; - - pResizeWndProc ResizeWndCallback; - - -}; - - -#endif +#ifndef CARDBOARD_INCLUDED +#define CARDBOARD_INCLUDED + +#define MAXBUTTONS 32 +#define MAXCARDSTACKS 32 +#define MAXDROPZONES 8 + +#include "dropzone.h" +#include "cardlib.h" + +class CardRegion; +class CardButton; + +LRESULT CALLBACK CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); + +class CardWindow +{ + friend class CardRegion; + friend class CardButton; + + friend void RegisterCardWindow(); + +public: + + CardWindow(); + ~CardWindow(); + + // + // Basic windowing support + // + BOOL Create(HWND hwndParent, DWORD dwExStyle, DWORD dwStyle, int x, int y, int width, int height); + BOOL Destroy(); + + operator HWND() { return m_hWnd; } + + CardButton *CreateButton (int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height); + CardRegion *CreateRegion (int id, bool fVisible, int x, int y, int xoffset, int yoffset); + + CardButton *CardButtonFromId(int id); + CardRegion *CardRegionFromId(int id); + + bool DeleteButton(CardButton *pButton); + bool DeleteRegion(CardRegion *pRegion); + bool DeleteAll(); + + void SetBackColor(COLORREF cr); + COLORREF GetBackColor(); + void SetBackCardIdx(UINT uBackIdx); + void SetBackImage(HBITMAP hBitmap); + + void EmptyStacks(void); + void Redraw(void); + void Update(void); + + bool DistributeStacks(int nIdFrom, int nNumStacks, UINT xJustify, int xSpacing, int nStartX); + void SetResizeProc(pResizeWndProc proc); + int GetWidth() { return nWidth; } + int GetHeight() { return nHeight; } + + // + // Dropzone support + // + bool RegisterDropZone(int id, RECT *rect, pDropZoneProc proc); + bool DeleteDropZone(int id); + +private: + + int GetNumDropZones() { return nNumDropZones; } + DropZone* GetDropZoneFromRect(RECT *rect); + + // + // Window procedure - don't call + // + LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK CardWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); + + // + // Private functions + // + void Paint(HDC hdc); + void PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy); + + HPALETTE CreateCardPalette(); + + CardButton *CardButtonFromPoint(int x, int y); + CardRegion *CardRegionFromPoint(int x, int y); + CardRegion *GetBestStack(int x, int y, int w, int h); + + // + // Private members + // + + HWND m_hWnd; //window handle! + int nWidth, nHeight; + + UINT nBackCardIdx; //all stacks share this card index by default + + HBITMAP hbmBackImage; + HDC hdcBackImage; + + + CardButton * Buttons[MAXBUTTONS]; + int nNumButtons; + + CardRegion * Regions[MAXCARDSTACKS]; + int nNumCardRegions; + + DropZone * dropzone[MAXDROPZONES]; + int nNumDropZones; + + COLORREF crBackgnd; + + pResizeWndProc ResizeWndCallback; + + +}; + + +#endif diff --git a/rosapps/games/solitaire/cardlib/dropzone.cpp b/rosapps/games/solitaire/cardlib/dropzone.cpp index 63a4af5caab..d3ec111b460 100644 --- a/rosapps/games/solitaire/cardlib/dropzone.cpp +++ b/rosapps/games/solitaire/cardlib/dropzone.cpp @@ -1,69 +1,69 @@ -// -// CardLib - DropZone class -// -// Freeware -// Copyright J Brown 2001 -// -#include - -#include "cardlib.h" -#include "cardwindow.h" -#include "dropzone.h" - -bool CardWindow::RegisterDropZone(int id, RECT *rect, pDropZoneProc proc) -{ - if(nNumDropZones == MAXDROPZONES) - return false; - - DropZone *dz = new DropZone(id, rect, proc); - - dropzone[nNumDropZones++] = dz; - - return false; -} - -DropZone *CardWindow::GetDropZoneFromRect(RECT *rect) -{ - for(int i = 0; i < nNumDropZones; i++) - { - RECT inter; - RECT zone; - - //if any part of the drag rectangle falls within a drop zone, - //let that take priority over any other card stack. - dropzone[i]->GetZone(&zone); - - if(IntersectRect(&inter, rect, &zone)) - { - //see if the callback wants us to drop a card on - //a particular stack - return dropzone[i]; - } - } - - return 0; -} - -bool CardWindow::DeleteDropZone(int id) -{ - for(int i = 0; i < nNumDropZones; i++) - { - if(dropzone[i]->id == id) - { - DropZone *dz = dropzone[i]; - - //shift any after this one backwards - for(int j = i; j < nNumDropZones - 1; j++) - { - dropzone[j] = dropzone[j + 1]; - } - - delete dz; - nNumDropZones--; - return true; - } - } - - return false; -} - +// +// CardLib - DropZone class +// +// Freeware +// Copyright J Brown 2001 +// +#include + +#include "cardlib.h" +#include "cardwindow.h" +#include "dropzone.h" + +bool CardWindow::RegisterDropZone(int id, RECT *rect, pDropZoneProc proc) +{ + if(nNumDropZones == MAXDROPZONES) + return false; + + DropZone *dz = new DropZone(id, rect, proc); + + dropzone[nNumDropZones++] = dz; + + return false; +} + +DropZone *CardWindow::GetDropZoneFromRect(RECT *rect) +{ + for(int i = 0; i < nNumDropZones; i++) + { + RECT inter; + RECT zone; + + //if any part of the drag rectangle falls within a drop zone, + //let that take priority over any other card stack. + dropzone[i]->GetZone(&zone); + + if(IntersectRect(&inter, rect, &zone)) + { + //see if the callback wants us to drop a card on + //a particular stack + return dropzone[i]; + } + } + + return 0; +} + +bool CardWindow::DeleteDropZone(int id) +{ + for(int i = 0; i < nNumDropZones; i++) + { + if(dropzone[i]->id == id) + { + DropZone *dz = dropzone[i]; + + //shift any after this one backwards + for(int j = i; j < nNumDropZones - 1; j++) + { + dropzone[j] = dropzone[j + 1]; + } + + delete dz; + nNumDropZones--; + return true; + } + } + + return false; +} + diff --git a/rosapps/games/solitaire/cardlib/dropzone.h b/rosapps/games/solitaire/cardlib/dropzone.h index 2f5d0802fa0..65224eb5695 100644 --- a/rosapps/games/solitaire/cardlib/dropzone.h +++ b/rosapps/games/solitaire/cardlib/dropzone.h @@ -1,39 +1,39 @@ -#ifndef DROPZONE_INCLUDED -#define DROPZONE_INCLUDED - -// -// define a drop-zone, which can be used to over-ride -// drop-behaviour for any card stacks which fall under it -// - -class CardStack; - -class DropZone -{ - friend class CardWindow; - - DropZone(int Id, RECT *rect, pDropZoneProc proc) : - id(Id), DropZoneCallback(proc) { CopyRect(&zone, rect); } - -public: - - void SetZone(RECT *rect) { CopyRect(&zone, rect); } - void GetZone(RECT *rect) { CopyRect(rect, &zone); } - void SetCallback(pDropZoneProc callback) { DropZoneCallback = callback; } - - int DropCards(CardStack &cardstack) - { - if(DropZoneCallback) - return DropZoneCallback(id, cardstack); - else - return -1; - } - -private: - - int id; - RECT zone; - pDropZoneProc DropZoneCallback; -}; - -#endif +#ifndef DROPZONE_INCLUDED +#define DROPZONE_INCLUDED + +// +// define a drop-zone, which can be used to over-ride +// drop-behaviour for any card stacks which fall under it +// + +class CardStack; + +class DropZone +{ + friend class CardWindow; + + DropZone(int Id, RECT *rect, pDropZoneProc proc) : + id(Id), DropZoneCallback(proc) { CopyRect(&zone, rect); } + +public: + + void SetZone(RECT *rect) { CopyRect(&zone, rect); } + void GetZone(RECT *rect) { CopyRect(rect, &zone); } + void SetCallback(pDropZoneProc callback) { DropZoneCallback = callback; } + + int DropCards(CardStack &cardstack) + { + if(DropZoneCallback) + return DropZoneCallback(id, cardstack); + else + return -1; + } + +private: + + int id; + RECT zone; + pDropZoneProc DropZoneCallback; +}; + +#endif diff --git a/rosapps/games/solitaire/cardlib/globals.h b/rosapps/games/solitaire/cardlib/globals.h index e4cdb48013c..329d2520852 100644 --- a/rosapps/games/solitaire/cardlib/globals.h +++ b/rosapps/games/solitaire/cardlib/globals.h @@ -1,15 +1,15 @@ -#ifndef GLOBALS_INCLUDED -#define GLOBALS_INCLUDED - -extern int __cardwidth; -extern int __cardheight; - -extern HDC __hdcCardBitmaps; -extern HBITMAP __hbmCardBitmaps; - -extern HDC __hdcPlaceHolder; -extern HBITMAP __hbmPlaceHolder; - -extern HPALETTE __hPalette; - -#endif +#ifndef GLOBALS_INCLUDED +#define GLOBALS_INCLUDED + +extern int __cardwidth; +extern int __cardheight; + +extern HDC __hdcCardBitmaps; +extern HBITMAP __hbmCardBitmaps; + +extern HDC __hdcPlaceHolder; +extern HBITMAP __hbmPlaceHolder; + +extern HPALETTE __hPalette; + +#endif diff --git a/rosapps/games/solitaire/solcreate.cpp b/rosapps/games/solitaire/solcreate.cpp index 0efb23a9520..622f2a6b3ab 100644 --- a/rosapps/games/solitaire/solcreate.cpp +++ b/rosapps/games/solitaire/solcreate.cpp @@ -1,84 +1,84 @@ -#include -#include -#include -#include "resource.h" -#include "cardlib/cardlib.h" - -#include "solitaire.h" - -const int yBorder = 20; -const int xBorder = 20; -const int yRowStacks = yBorder + 128; - -CardRegion *pDeck; -CardRegion *pPile; -CardRegion *pSuitStack[4]; -CardRegion *pRowStack[NUM_ROW_STACKS]; - -extern CardStack activepile; - -HBITMAP hbmBitmap; -HDC hdcBitmap; - -void CreateSol() -{ - int i; - -// hbmBitmap = (HBITMAP)LoadImage(0,"test.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); -// SolWnd.SetBackImage(hbmBitmap); - - activepile.Clear(); - - - pDeck = SolWnd.CreateRegion(DECK_ID, true, xBorder, yBorder, 2, 1); - pDeck->SetEmptyImage(CS_EI_SUNK); - pDeck->SetThreedCount(6); - pDeck->SetDragRule(CS_DRAG_NONE, 0); - pDeck->SetDropRule(CS_DROP_NONE, 0); - pDeck->SetClickProc(DeckClickProc); - pDeck->SetDblClickProc(DeckClickProc); - pDeck->SetFaceDirection(CS_FACE_DOWN, 0); - - pPile = SolWnd.CreateRegion(PILE_ID, true, 110, yBorder, CS_DEFXOFF, 1); - pPile->SetEmptyImage(CS_EI_NONE); - pPile->SetDragRule(CS_DRAG_TOP, 0); - pPile->SetDropRule(CS_DROP_NONE, 0); - pPile->SetDblClickProc(PileDblClickProc); - pPile->SetRemoveCardProc(PileRemoveProc); - - // - // Create the suit stacks - // - for(i = 0; i < 4; i++) - { - pSuitStack[i] = SolWnd.CreateRegion(SUIT_ID+i, true, 0, yBorder, 0, 0); - pSuitStack[i]->SetEmptyImage(CS_EI_SUNK); - //pSuitStack[i]->SetPlacement(CS_XJUST_RIGHT, 0, -i * (__cardwidth + 4) - xBorder, 0); - pSuitStack[i]->SetPlacement(CS_XJUST_CENTER, 0, i * (__cardwidth + 10) , 0); - - pSuitStack[i]->SetDropRule(CS_DROP_CALLBACK, SuitStackDropProc); - pSuitStack[i]->SetDragRule(CS_DRAG_TOP); - - pSuitStack[i]->SetAddCardProc(SuitStackAddProc); - } - - // - // Create the row stacks - // - for(i = 0; i < NUM_ROW_STACKS; i++) - { - pRowStack[i] = SolWnd.CreateRegion(ROW_ID+i, true, 0, yRowStacks, 0, 14); - pRowStack[i]->SetEmptyImage(CS_EI_SUNK); - pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i); - - pRowStack[i]->SetPlacement(CS_XJUST_CENTER, 0, - (i - NUM_ROW_STACKS/2) * (__cardwidth + 10), 0); - - pRowStack[i]->SetEmptyImage(CS_EI_NONE); - - pRowStack[i]->SetDragRule(CS_DRAG_CALLBACK, RowStackDragProc); - pRowStack[i]->SetDropRule(CS_DROP_CALLBACK, RowStackDropProc); - pRowStack[i]->SetClickProc(RowStackClickProc); - pRowStack[i]->SetDblClickProc(RowStackDblClickProc); - } -} +#include +#include +#include +#include "resource.h" +#include "cardlib/cardlib.h" + +#include "solitaire.h" + +const int yBorder = 20; +const int xBorder = 20; +const int yRowStacks = yBorder + 128; + +CardRegion *pDeck; +CardRegion *pPile; +CardRegion *pSuitStack[4]; +CardRegion *pRowStack[NUM_ROW_STACKS]; + +extern CardStack activepile; + +HBITMAP hbmBitmap; +HDC hdcBitmap; + +void CreateSol() +{ + int i; + +// hbmBitmap = (HBITMAP)LoadImage(0,"test.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); +// SolWnd.SetBackImage(hbmBitmap); + + activepile.Clear(); + + + pDeck = SolWnd.CreateRegion(DECK_ID, true, xBorder, yBorder, 2, 1); + pDeck->SetEmptyImage(CS_EI_SUNK); + pDeck->SetThreedCount(6); + pDeck->SetDragRule(CS_DRAG_NONE, 0); + pDeck->SetDropRule(CS_DROP_NONE, 0); + pDeck->SetClickProc(DeckClickProc); + pDeck->SetDblClickProc(DeckClickProc); + pDeck->SetFaceDirection(CS_FACE_DOWN, 0); + + pPile = SolWnd.CreateRegion(PILE_ID, true, 110, yBorder, CS_DEFXOFF, 1); + pPile->SetEmptyImage(CS_EI_NONE); + pPile->SetDragRule(CS_DRAG_TOP, 0); + pPile->SetDropRule(CS_DROP_NONE, 0); + pPile->SetDblClickProc(PileDblClickProc); + pPile->SetRemoveCardProc(PileRemoveProc); + + // + // Create the suit stacks + // + for(i = 0; i < 4; i++) + { + pSuitStack[i] = SolWnd.CreateRegion(SUIT_ID+i, true, 0, yBorder, 0, 0); + pSuitStack[i]->SetEmptyImage(CS_EI_SUNK); + //pSuitStack[i]->SetPlacement(CS_XJUST_RIGHT, 0, -i * (__cardwidth + 4) - xBorder, 0); + pSuitStack[i]->SetPlacement(CS_XJUST_CENTER, 0, i * (__cardwidth + 10) , 0); + + pSuitStack[i]->SetDropRule(CS_DROP_CALLBACK, SuitStackDropProc); + pSuitStack[i]->SetDragRule(CS_DRAG_TOP); + + pSuitStack[i]->SetAddCardProc(SuitStackAddProc); + } + + // + // Create the row stacks + // + for(i = 0; i < NUM_ROW_STACKS; i++) + { + pRowStack[i] = SolWnd.CreateRegion(ROW_ID+i, true, 0, yRowStacks, 0, 14); + pRowStack[i]->SetEmptyImage(CS_EI_SUNK); + pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i); + + pRowStack[i]->SetPlacement(CS_XJUST_CENTER, 0, + (i - NUM_ROW_STACKS/2) * (__cardwidth + 10), 0); + + pRowStack[i]->SetEmptyImage(CS_EI_NONE); + + pRowStack[i]->SetDragRule(CS_DRAG_CALLBACK, RowStackDragProc); + pRowStack[i]->SetDropRule(CS_DROP_CALLBACK, RowStackDropProc); + pRowStack[i]->SetClickProc(RowStackClickProc); + pRowStack[i]->SetDblClickProc(RowStackDblClickProc); + } +} diff --git a/rosapps/games/solitaire/solgame.cpp b/rosapps/games/solitaire/solgame.cpp index 35bb9653ab9..0442911858c 100644 --- a/rosapps/games/solitaire/solgame.cpp +++ b/rosapps/games/solitaire/solgame.cpp @@ -1,360 +1,360 @@ -#include -#include -#include -#include -#include "resource.h" -#include "cardlib/cardlib.h" -//#include "../catch22lib/trace.h" -#include "solitaire.h" - -#if 1 -#define TRACE(s) -#else -#define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s) -#endif - -CardStack activepile; -bool fGameStarted = false; - -void NewGame(void) -{ - TRACE("ENTER NewGame()\n"); - int i, j; - - SolWnd.EmptyStacks(); - - //create a new card-stack - CardStack deck; - deck.NewDeck(); - deck.Shuffle(); - activepile.Clear(); - - //deal to each row stack.. - for(i = 0; i < NUM_ROW_STACKS; i++) - { - CardStack temp; - temp.Clear(); - - pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i); - - for(j = 0; j <= i; j++) - { - temp.Push(deck.Pop()); - } - - pRowStack[i]->SetCardStack(temp); - } - - //put the other cards onto the deck - pDeck->SetCardStack(deck); - pDeck->Update(); - - SolWnd.Redraw(); - - fGameStarted = false; - TRACE("EXIT NewGame()\n"); -} - -// -// Now follow the stack callback functions. This is where we -// provide the game functionality and rules -// - -// -// Can only drag face-up cards -// -bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumDragCards) -{ - TRACE("ENTER RowStackDragProc()\n"); - int numfacedown; - int numcards; - - stackobj.GetFaceDirection(&numfacedown); - - numcards = stackobj.NumCards(); - - TRACE("EXIT RowStackDragProc()\n"); - if(iNumDragCards <= numcards-numfacedown) - return true; - else - return false; - -} - -// -// Row a row-stack, we can only drop cards -// that are lower / different colour -// -bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, const CardStack &dragcards) -{ - TRACE("ENTER RowStackDropProc()\n"); - Card dragcard = dragcards[dragcards.NumCards() - 1]; - - //if we are empty, can only drop a stack with a King at bottom - if(stackobj.NumCards() == 0) - { - if(dragcard.LoVal() != 13) - { - TRACE("EXIT RowStackDropProc(false)\n"); - return false; - } - } - else - { - const CardStack &mystack = stackobj.GetCardStack(); - - //can only drop if card is 1 less - if(mystack[0].LoVal() != dragcard.LoVal() + 1) - { - TRACE("EXIT RowStackDropProc(false)\n"); - return false; - } - - //can only drop if card is different colour - if( mystack[0].IsBlack() && !dragcard.IsRed() || - !mystack[0].IsBlack() && dragcard.IsRed() ) - { - TRACE("EXIT RowStackDropProc(false)\n"); - return false; - } - } - - TRACE("EXIT RowStackDropProc(true)\n"); - return true; -} - -// -// Can only drop a card onto a suit-stack if the -// card is 1 higher, and is the same suit -// -bool CanDrop(CardRegion &stackobj, Card card) -{ - TRACE("ENTER CanDrop()\n"); - int topval; - - const CardStack &cardstack = stackobj.GetCardStack(); - - if(cardstack.NumCards() > 0) - { - if(card.Suit() != cardstack[0].Suit()) - { - TRACE("EXIT CanDrop()\n"); - return false; - } - - topval = cardstack[0].LoVal(); - } - else - { - topval = 0; - } - - //make sure 1 higher - if(card.LoVal() != (topval + 1)) - { - TRACE("EXIT CanDrop()\n"); - return false; - } - - TRACE("EXIT CanDrop()\n"); - return true; -} - -// -// Can only drop a card onto suit stack if it is same suit, and 1 higher -// -bool CARDLIBPROC SuitStackDropProc(CardRegion &stackobj, const CardStack &dragcards) -{ - TRACE("ENTER SuitStackDropProc()\n"); - //only drop 1 card at a time - if(dragcards.NumCards() != 1) - { - TRACE("EXIT SuitStackDropProc()\n"); - return false; - } - - bool b = CanDrop(stackobj, dragcards[0]); - TRACE("EXIT SuitStackDropProc()\n"); - return b; -} - -// -// Single-click on one of the row-stacks -// Turn the top-card over if they are all face-down -// -void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int iNumClicked) -{ - TRACE("ENTER RowStackClickProc()\n"); - int numfacedown; - - stackobj.GetFaceDirection(&numfacedown); - - //if all face-down, then make top card face-up - if(stackobj.NumCards() == numfacedown) - { - if(numfacedown > 0) numfacedown--; - stackobj.SetFaceDirection(CS_FACE_DOWNUP, numfacedown); - stackobj.Redraw(); - } - TRACE("EXIT RowStackClickProc()\n"); -} - -// -// Find the suit-stack that can accept the specified card -// -CardRegion *FindSuitStackFromCard(Card card) -{ - TRACE("ENTER FindSuitStackFromCard()\n"); - for(int i = 0; i < 4; i++) - { - if(CanDrop(*pSuitStack[i], card)) - { - TRACE("EXIT FindSuitStackFromCard()\n"); - return pSuitStack[i]; - } - } - - TRACE("EXIT FindSuitStackFromCard()\n"); - return 0; -} - -// -// What happens when we add a card to one of the suit stacks? -// Well, nothing (it is already added), but we need to -// check all four stacks (not just this one) to see if -// the game has finished. -// -void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const CardStack &added) -{ - TRACE("ENTER SuitStackAddProc()\n"); - bool fGameOver = true; - - for(int i = 0; i < 4; i++) - { - if(pSuitStack[i]->NumCards() != 13) - { - fGameOver = false; - break; - } - } - - if(fGameOver) - { - MessageBox(SolWnd, _T("Congratulations, you win!!"), szAppName, MB_OK | MB_ICONINFORMATION); - - for(int i = 0; i < 4; i++) - { - pSuitStack[i]->Flash(11, 100); - } - } - TRACE("EXIT SuitStackAddProc()\n"); -} - -// -// Double-click on one of the row stacks -// The aim is to find a suit-stack to move the -// double-clicked card to. -// -void CARDLIBPROC RowStackDblClickProc(CardRegion &stackobj, int iNumClicked) -{ - TRACE("ENTER RowStackDblClickProc()\n"); - //can only move 1 card at a time - if(iNumClicked != 1) - { - TRACE("EXIT RowStackDblClickProc()\n"); - return; - } - - //find a suit-stack to move the card to... - const CardStack &cardstack = stackobj.GetCardStack(); - CardRegion *pDest = FindSuitStackFromCard(cardstack[0]); - - if(pDest != 0) - { - //stackobj.MoveCards(pDest, 1, true); - //use the SimulateDrag funcion, because we get the - //AddProc callbacks called for us on the destination stacks... - stackobj.SimulateDrag(pDest, 1, true); - } - TRACE("EXIT RowStackDblClickProc()\n"); -} - -// -// Face-up pile double-click -// -void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int iNumClicked) -{ - TRACE("ENTER PileDblClickProc()\n"); - RowStackDblClickProc(stackobj, iNumClicked); - TRACE("EXIT PileDblClickProc()\n"); -} - -// -// What happens when a card is removed from face-up pile? -// -void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iItems) -{ - TRACE("ENTER PileRemoveProc()\n"); - //modify our "virtual" pile by removing the same card - //that was removed from the physical card stack - activepile.Pop(iItems); - - //if there is just 1 card left, then modify the - //stack to contain ALL the face-up cards..the effect - //will be, the next time a card is dragged, all the - //previous card-triplets will be available underneath - if(stackobj.NumCards() == 1) - { - stackobj.SetOffsets(0,0); - stackobj.SetCardStack(activepile); - } - TRACE("EXIT PileRemoveProc()\n"); -} - -// -// Double-click on the deck -// Move 3 cards to the face-up pile -// -void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked) -{ - TRACE("ENTER DeckClickProc()\n"); - CardStack cardstack = stackobj.GetCardStack(); - CardStack pile = pPile->GetCardStack(); - - fGameStarted = true; - - //reset the face-up pile to represent 3 cards - pPile->SetOffsets(CS_DEFXOFF, 1); - - if(cardstack.NumCards() == 0) - { - pile.Clear(); - - activepile.Reverse(); - cardstack.Push(activepile); - activepile.Clear(); - } - else - { - int numcards = min(3, cardstack.NumCards()); - - //make a "visible" copy of these cards - CardStack temp; - temp = cardstack.Pop(numcards); - temp.Reverse(); - - pile.Clear(); - pile.Push(temp); - - //remove the top 3 from deck - activepile.Push(temp); - } - - activepile.Print(); - - pDeck->SetCardStack(cardstack); - pPile->SetCardStack(pile); - - SolWnd.Redraw(); - TRACE("EXIT DeckClickProc()\n"); -} +#include +#include +#include +#include +#include "resource.h" +#include "cardlib/cardlib.h" +//#include "../catch22lib/trace.h" +#include "solitaire.h" + +#if 1 +#define TRACE(s) +#else +#define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s) +#endif + +CardStack activepile; +bool fGameStarted = false; + +void NewGame(void) +{ + TRACE("ENTER NewGame()\n"); + int i, j; + + SolWnd.EmptyStacks(); + + //create a new card-stack + CardStack deck; + deck.NewDeck(); + deck.Shuffle(); + activepile.Clear(); + + //deal to each row stack.. + for(i = 0; i < NUM_ROW_STACKS; i++) + { + CardStack temp; + temp.Clear(); + + pRowStack[i]->SetFaceDirection(CS_FACE_DOWNUP, i); + + for(j = 0; j <= i; j++) + { + temp.Push(deck.Pop()); + } + + pRowStack[i]->SetCardStack(temp); + } + + //put the other cards onto the deck + pDeck->SetCardStack(deck); + pDeck->Update(); + + SolWnd.Redraw(); + + fGameStarted = false; + TRACE("EXIT NewGame()\n"); +} + +// +// Now follow the stack callback functions. This is where we +// provide the game functionality and rules +// + +// +// Can only drag face-up cards +// +bool CARDLIBPROC RowStackDragProc(CardRegion &stackobj, int iNumDragCards) +{ + TRACE("ENTER RowStackDragProc()\n"); + int numfacedown; + int numcards; + + stackobj.GetFaceDirection(&numfacedown); + + numcards = stackobj.NumCards(); + + TRACE("EXIT RowStackDragProc()\n"); + if(iNumDragCards <= numcards-numfacedown) + return true; + else + return false; + +} + +// +// Row a row-stack, we can only drop cards +// that are lower / different colour +// +bool CARDLIBPROC RowStackDropProc(CardRegion &stackobj, const CardStack &dragcards) +{ + TRACE("ENTER RowStackDropProc()\n"); + Card dragcard = dragcards[dragcards.NumCards() - 1]; + + //if we are empty, can only drop a stack with a King at bottom + if(stackobj.NumCards() == 0) + { + if(dragcard.LoVal() != 13) + { + TRACE("EXIT RowStackDropProc(false)\n"); + return false; + } + } + else + { + const CardStack &mystack = stackobj.GetCardStack(); + + //can only drop if card is 1 less + if(mystack[0].LoVal() != dragcard.LoVal() + 1) + { + TRACE("EXIT RowStackDropProc(false)\n"); + return false; + } + + //can only drop if card is different colour + if( mystack[0].IsBlack() && !dragcard.IsRed() || + !mystack[0].IsBlack() && dragcard.IsRed() ) + { + TRACE("EXIT RowStackDropProc(false)\n"); + return false; + } + } + + TRACE("EXIT RowStackDropProc(true)\n"); + return true; +} + +// +// Can only drop a card onto a suit-stack if the +// card is 1 higher, and is the same suit +// +bool CanDrop(CardRegion &stackobj, Card card) +{ + TRACE("ENTER CanDrop()\n"); + int topval; + + const CardStack &cardstack = stackobj.GetCardStack(); + + if(cardstack.NumCards() > 0) + { + if(card.Suit() != cardstack[0].Suit()) + { + TRACE("EXIT CanDrop()\n"); + return false; + } + + topval = cardstack[0].LoVal(); + } + else + { + topval = 0; + } + + //make sure 1 higher + if(card.LoVal() != (topval + 1)) + { + TRACE("EXIT CanDrop()\n"); + return false; + } + + TRACE("EXIT CanDrop()\n"); + return true; +} + +// +// Can only drop a card onto suit stack if it is same suit, and 1 higher +// +bool CARDLIBPROC SuitStackDropProc(CardRegion &stackobj, const CardStack &dragcards) +{ + TRACE("ENTER SuitStackDropProc()\n"); + //only drop 1 card at a time + if(dragcards.NumCards() != 1) + { + TRACE("EXIT SuitStackDropProc()\n"); + return false; + } + + bool b = CanDrop(stackobj, dragcards[0]); + TRACE("EXIT SuitStackDropProc()\n"); + return b; +} + +// +// Single-click on one of the row-stacks +// Turn the top-card over if they are all face-down +// +void CARDLIBPROC RowStackClickProc(CardRegion &stackobj, int iNumClicked) +{ + TRACE("ENTER RowStackClickProc()\n"); + int numfacedown; + + stackobj.GetFaceDirection(&numfacedown); + + //if all face-down, then make top card face-up + if(stackobj.NumCards() == numfacedown) + { + if(numfacedown > 0) numfacedown--; + stackobj.SetFaceDirection(CS_FACE_DOWNUP, numfacedown); + stackobj.Redraw(); + } + TRACE("EXIT RowStackClickProc()\n"); +} + +// +// Find the suit-stack that can accept the specified card +// +CardRegion *FindSuitStackFromCard(Card card) +{ + TRACE("ENTER FindSuitStackFromCard()\n"); + for(int i = 0; i < 4; i++) + { + if(CanDrop(*pSuitStack[i], card)) + { + TRACE("EXIT FindSuitStackFromCard()\n"); + return pSuitStack[i]; + } + } + + TRACE("EXIT FindSuitStackFromCard()\n"); + return 0; +} + +// +// What happens when we add a card to one of the suit stacks? +// Well, nothing (it is already added), but we need to +// check all four stacks (not just this one) to see if +// the game has finished. +// +void CARDLIBPROC SuitStackAddProc(CardRegion &stackobj, const CardStack &added) +{ + TRACE("ENTER SuitStackAddProc()\n"); + bool fGameOver = true; + + for(int i = 0; i < 4; i++) + { + if(pSuitStack[i]->NumCards() != 13) + { + fGameOver = false; + break; + } + } + + if(fGameOver) + { + MessageBox(SolWnd, _T("Congratulations, you win!!"), szAppName, MB_OK | MB_ICONINFORMATION); + + for(int i = 0; i < 4; i++) + { + pSuitStack[i]->Flash(11, 100); + } + } + TRACE("EXIT SuitStackAddProc()\n"); +} + +// +// Double-click on one of the row stacks +// The aim is to find a suit-stack to move the +// double-clicked card to. +// +void CARDLIBPROC RowStackDblClickProc(CardRegion &stackobj, int iNumClicked) +{ + TRACE("ENTER RowStackDblClickProc()\n"); + //can only move 1 card at a time + if(iNumClicked != 1) + { + TRACE("EXIT RowStackDblClickProc()\n"); + return; + } + + //find a suit-stack to move the card to... + const CardStack &cardstack = stackobj.GetCardStack(); + CardRegion *pDest = FindSuitStackFromCard(cardstack[0]); + + if(pDest != 0) + { + //stackobj.MoveCards(pDest, 1, true); + //use the SimulateDrag funcion, because we get the + //AddProc callbacks called for us on the destination stacks... + stackobj.SimulateDrag(pDest, 1, true); + } + TRACE("EXIT RowStackDblClickProc()\n"); +} + +// +// Face-up pile double-click +// +void CARDLIBPROC PileDblClickProc(CardRegion &stackobj, int iNumClicked) +{ + TRACE("ENTER PileDblClickProc()\n"); + RowStackDblClickProc(stackobj, iNumClicked); + TRACE("EXIT PileDblClickProc()\n"); +} + +// +// What happens when a card is removed from face-up pile? +// +void CARDLIBPROC PileRemoveProc(CardRegion &stackobj, int iItems) +{ + TRACE("ENTER PileRemoveProc()\n"); + //modify our "virtual" pile by removing the same card + //that was removed from the physical card stack + activepile.Pop(iItems); + + //if there is just 1 card left, then modify the + //stack to contain ALL the face-up cards..the effect + //will be, the next time a card is dragged, all the + //previous card-triplets will be available underneath + if(stackobj.NumCards() == 1) + { + stackobj.SetOffsets(0,0); + stackobj.SetCardStack(activepile); + } + TRACE("EXIT PileRemoveProc()\n"); +} + +// +// Double-click on the deck +// Move 3 cards to the face-up pile +// +void CARDLIBPROC DeckClickProc(CardRegion &stackobj, int iNumClicked) +{ + TRACE("ENTER DeckClickProc()\n"); + CardStack cardstack = stackobj.GetCardStack(); + CardStack pile = pPile->GetCardStack(); + + fGameStarted = true; + + //reset the face-up pile to represent 3 cards + pPile->SetOffsets(CS_DEFXOFF, 1); + + if(cardstack.NumCards() == 0) + { + pile.Clear(); + + activepile.Reverse(); + cardstack.Push(activepile); + activepile.Clear(); + } + else + { + int numcards = min(3, cardstack.NumCards()); + + //make a "visible" copy of these cards + CardStack temp; + temp = cardstack.Pop(numcards); + temp.Reverse(); + + pile.Clear(); + pile.Push(temp); + + //remove the top 3 from deck + activepile.Push(temp); + } + + activepile.Print(); + + pDeck->SetCardStack(cardstack); + pPile->SetCardStack(pile); + + SolWnd.Redraw(); + TRACE("EXIT DeckClickProc()\n"); +} diff --git a/rosapps/games/solitaire/solitaire.cpp b/rosapps/games/solitaire/solitaire.cpp index dc2faf80fcb..92b57a1e8fe 100644 --- a/rosapps/games/solitaire/solitaire.cpp +++ b/rosapps/games/solitaire/solitaire.cpp @@ -1,222 +1,222 @@ -#include -#include -#include -#include "resource.h" -#include "cardlib/cardlib.h" - -#include "solitaire.h" - -TCHAR szHelpPath[MAX_PATH]; - -DWORD dwAppStartTime; -HWND hwndMain; -HWND hwndStatus; -HINSTANCE hInstance; - -TCHAR szAppName[] = _T("Solitaire"); - -CardWindow SolWnd; - -LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); - -void MakePath(TCHAR *szDest, UINT nDestLen, TCHAR *szExt) -{ - TCHAR *ptr; - - ptr = szDest + GetModuleFileName(GetModuleHandle(0), szDest, nDestLen) - 1; - while(*ptr-- != '.'); - lstrcpy(ptr + 1, szExt); -} - -int main ( int argc, char** argv ) -{ - return WinMain ( NULL, NULL, NULL, SW_SHOW ); -} - -// -// Main entry point -// -int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, PSTR szCmdLine, int iCmdShow) -{ - HWND hwnd; - MSG msg; - WNDCLASSEX wndclass; - INITCOMMONCONTROLSEX ice; - HACCEL hAccelTable; - - hInstance = hInst; - - //Window class for the main application parent window - wndclass.cbSize = sizeof(wndclass); - wndclass.style = 0;//CS_HREDRAW | CS_VREDRAW; - wndclass.lpfnWndProc = WndProc; - wndclass.cbClsExtra = 0; - wndclass.cbWndExtra = 0; - wndclass.hInstance = hInst; - wndclass.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(IDI_ICON1)); - wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); - wndclass.hbrBackground = (HBRUSH)NULL; - wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); - wndclass.lpszClassName = szAppName; - wndclass.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 16, 16, 0); - - RegisterClassEx(&wndclass); - - ice.dwSize = sizeof(ice); - ice.dwICC = ICC_BAR_CLASSES; - InitCommonControlsEx(&ice); - - srand((unsigned)GetTickCount());//timeGetTime()); - -// InitCardLib(); - -// LoadSettings(); - - //Construct the path to our help file - MakePath(szHelpPath, MAX_PATH, _T(".hlp")); - - hwnd = CreateWindow(szAppName, // window class name - szAppName, // window caption - WS_OVERLAPPEDWINDOW - ,//|WS_CLIPCHILDREN, // window style - CW_USEDEFAULT, // initial x position - CW_USEDEFAULT, // initial y position - CW_USEDEFAULT, // initial x size - CW_USEDEFAULT, // initial y size - NULL, // parent window handle - NULL, // use window class menu - hInst, // program instance handle - NULL); // creation parameters - - hwndMain = hwnd; - - ShowWindow(hwnd, iCmdShow); - UpdateWindow(hwnd); - - hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1)); - - while(GetMessage(&msg, NULL,0,0)) - { - if(!TranslateAccelerator(hwnd, hAccelTable, &msg)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - -// SaveSettings(); - - return msg.wParam; -} - - -//----------------------------------------------------------------------------- -LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) -{ - static int nWidth, nHeight; - int nStatusHeight = 0;//20; - int parts[] = { 100, -1 }; - UINT ret; - - MINMAXINFO *mmi; - - switch(iMsg) - { - case WM_CREATE: - hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, "Ready", hwnd, 0); - - //SendMessage(hwndStatus, SB_SIMPLE, (WPARAM)TRUE, 0); - - SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts); - SendMessage(hwndStatus, SB_SETTEXT, 0 | SBT_NOBORDERS, (LPARAM)""); - - ShowWindow(hwndStatus, SW_HIDE); - - SolWnd.Create(hwnd, WS_EX_CLIENTEDGE, WS_CHILD|WS_VISIBLE, 0, 0, 0, 0); - - CreateSol(); - - NewGame(); - - dwAppStartTime = GetTickCount(); - - return 0; - - case WM_DESTROY: - PostQuitMessage(0); - return 0; - - case WM_SIZE: - nWidth = LOWORD(lParam); - nHeight = HIWORD(lParam); - - MoveWindow(SolWnd, 0, 0, nWidth, nHeight-nStatusHeight, TRUE); - //MoveWindow(hwndStatus, 0, nHeight-nStatusHeight, nWidth, nHeight, TRUE); - //parts[0] = nWidth - 256; - //SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts); - - return 0; - - case WM_GETMINMAXINFO: - mmi = (MINMAXINFO *)lParam; - mmi->ptMinTrackSize.x = 600; - mmi->ptMinTrackSize.y = 400; - - return 0; - - case WM_COMMAND: - - switch(LOWORD(wParam)) - { - case IDM_GAME_NEW: - //simulate a button click on the new button.. - NewGame(); - return 0; - - case IDM_GAME_DECK: - //ShowDeckOptionsDlg(hwnd); - return 0; - - case IDM_GAME_OPTIONS: - //ShowGameOptionsDlg(hwnd); - return 0; - - case IDM_HELP_CONTENTS: - - WinHelp(hwnd, szHelpPath, HELP_CONTENTS, 0);//HELP_KEY, (DWORD)"How to play"); - - return 0; - - case IDM_HELP_ABOUT: - MessageBox(hwnd, _T("Solitare by J Brown\r\n\r\nCardLib version 1.0."), szAppName, MB_OK|MB_ICONINFORMATION); - - return 0; - - case IDM_GAME_EXIT: - PostMessage(hwnd, WM_CLOSE, 0, 0); - return 0; - } - - return 0; - - case WM_CLOSE: - - ret = IDOK; - - if(fGameStarted) - { - ret = MessageBox(hwnd, _T("Quit the current game?"), szAppName, MB_OKCANCEL|MB_ICONQUESTION); - } - - if(ret == IDOK) - { - WinHelp(hwnd, szHelpPath, HELP_QUIT, 0); - DestroyWindow(hwnd); - } - - return 0; - } - - return DefWindowProc (hwnd, iMsg, wParam, lParam); -} - +#include +#include +#include +#include "resource.h" +#include "cardlib/cardlib.h" + +#include "solitaire.h" + +TCHAR szHelpPath[MAX_PATH]; + +DWORD dwAppStartTime; +HWND hwndMain; +HWND hwndStatus; +HINSTANCE hInstance; + +TCHAR szAppName[] = _T("Solitaire"); + +CardWindow SolWnd; + +LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); + +void MakePath(TCHAR *szDest, UINT nDestLen, TCHAR *szExt) +{ + TCHAR *ptr; + + ptr = szDest + GetModuleFileName(GetModuleHandle(0), szDest, nDestLen) - 1; + while(*ptr-- != '.'); + lstrcpy(ptr + 1, szExt); +} + +int main ( int argc, char** argv ) +{ + return WinMain ( NULL, NULL, NULL, SW_SHOW ); +} + +// +// Main entry point +// +int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, PSTR szCmdLine, int iCmdShow) +{ + HWND hwnd; + MSG msg; + WNDCLASSEX wndclass; + INITCOMMONCONTROLSEX ice; + HACCEL hAccelTable; + + hInstance = hInst; + + //Window class for the main application parent window + wndclass.cbSize = sizeof(wndclass); + wndclass.style = 0;//CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(IDI_ICON1)); + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)NULL; + wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); + wndclass.lpszClassName = szAppName; + wndclass.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 16, 16, 0); + + RegisterClassEx(&wndclass); + + ice.dwSize = sizeof(ice); + ice.dwICC = ICC_BAR_CLASSES; + InitCommonControlsEx(&ice); + + srand((unsigned)GetTickCount());//timeGetTime()); + +// InitCardLib(); + +// LoadSettings(); + + //Construct the path to our help file + MakePath(szHelpPath, MAX_PATH, _T(".hlp")); + + hwnd = CreateWindow(szAppName, // window class name + szAppName, // window caption + WS_OVERLAPPEDWINDOW + ,//|WS_CLIPCHILDREN, // window style + CW_USEDEFAULT, // initial x position + CW_USEDEFAULT, // initial y position + CW_USEDEFAULT, // initial x size + CW_USEDEFAULT, // initial y size + NULL, // parent window handle + NULL, // use window class menu + hInst, // program instance handle + NULL); // creation parameters + + hwndMain = hwnd; + + ShowWindow(hwnd, iCmdShow); + UpdateWindow(hwnd); + + hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1)); + + while(GetMessage(&msg, NULL,0,0)) + { + if(!TranslateAccelerator(hwnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + +// SaveSettings(); + + return msg.wParam; +} + + +//----------------------------------------------------------------------------- +LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + static int nWidth, nHeight; + int nStatusHeight = 0;//20; + int parts[] = { 100, -1 }; + UINT ret; + + MINMAXINFO *mmi; + + switch(iMsg) + { + case WM_CREATE: + hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, "Ready", hwnd, 0); + + //SendMessage(hwndStatus, SB_SIMPLE, (WPARAM)TRUE, 0); + + SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts); + SendMessage(hwndStatus, SB_SETTEXT, 0 | SBT_NOBORDERS, (LPARAM)""); + + ShowWindow(hwndStatus, SW_HIDE); + + SolWnd.Create(hwnd, WS_EX_CLIENTEDGE, WS_CHILD|WS_VISIBLE, 0, 0, 0, 0); + + CreateSol(); + + NewGame(); + + dwAppStartTime = GetTickCount(); + + return 0; + + case WM_DESTROY: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + nWidth = LOWORD(lParam); + nHeight = HIWORD(lParam); + + MoveWindow(SolWnd, 0, 0, nWidth, nHeight-nStatusHeight, TRUE); + //MoveWindow(hwndStatus, 0, nHeight-nStatusHeight, nWidth, nHeight, TRUE); + //parts[0] = nWidth - 256; + //SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts); + + return 0; + + case WM_GETMINMAXINFO: + mmi = (MINMAXINFO *)lParam; + mmi->ptMinTrackSize.x = 600; + mmi->ptMinTrackSize.y = 400; + + return 0; + + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case IDM_GAME_NEW: + //simulate a button click on the new button.. + NewGame(); + return 0; + + case IDM_GAME_DECK: + //ShowDeckOptionsDlg(hwnd); + return 0; + + case IDM_GAME_OPTIONS: + //ShowGameOptionsDlg(hwnd); + return 0; + + case IDM_HELP_CONTENTS: + + WinHelp(hwnd, szHelpPath, HELP_CONTENTS, 0);//HELP_KEY, (DWORD)"How to play"); + + return 0; + + case IDM_HELP_ABOUT: + MessageBox(hwnd, _T("Solitare by J Brown\r\n\r\nCardLib version 1.0."), szAppName, MB_OK|MB_ICONINFORMATION); + + return 0; + + case IDM_GAME_EXIT: + PostMessage(hwnd, WM_CLOSE, 0, 0); + return 0; + } + + return 0; + + case WM_CLOSE: + + ret = IDOK; + + if(fGameStarted) + { + ret = MessageBox(hwnd, _T("Quit the current game?"), szAppName, MB_OKCANCEL|MB_ICONQUESTION); + } + + if(ret == IDOK) + { + WinHelp(hwnd, szHelpPath, HELP_QUIT, 0); + DestroyWindow(hwnd); + } + + return 0; + } + + return DefWindowProc (hwnd, iMsg, wParam, lParam); +} + diff --git a/rosapps/packmgr/cmd-line/main.c b/rosapps/packmgr/cmd-line/main.c index 07cb911de45..0cbd6df21b4 100644 --- a/rosapps/packmgr/cmd-line/main.c +++ b/rosapps/packmgr/cmd-line/main.c @@ -1,206 +1,206 @@ -//////////////////////////////////////////////////////// -// -// main.cpp -// -// Implementation of a Commandlne Interface -// for the ReactOs Package Manager -// -// Maarten Bosma, 09.01.2004 -// maarten.paul@bosma.de -// -//////////////////////////////////////////////////////////////////// - -#include "main.h" -#include - - -int main (int argc, char **argv) -{ - wprintf(L"ReactOs PackageManager %d.%d.%d Commandline Interface \n\n", PACKMGR_VERSION_MAJOR, PACKMGR_VERSION_MINOR, PACKMGR_VERSION_PATCH_LEVEL); - Argv = argv; Argc = argc; - - if(argc<2) - return Help(); - - // install a package - if (!strcmp(argv[1], "install")) - Install(); - - // install a package from source - else if (!strcmp(argv[1], "src-inst")) - { - wprintf(L"Sorry but I can't do that yet. \n"); - } - - // update a package - else if (!strcmp(argv[1], "update")) - { - wprintf(L"Sorry but I can't do that yet. \n"); - } - - // update everything - else if (!strcmp(argv[1], "dist-upgrade")) - { - wprintf(L"Sorry but I can't do that yet. \n"); - } - - // remove a package - else if (!strcmp(argv[1], "remove")) - { - wprintf(L"Sorry but I can't do that yet. \n"); - } - - // search for a package - else if (!strcmp(argv[1], "show")) - { - Show(); - } - - // search for a package - else if (!strcmp(argv[1], "search")) - { - wprintf(L"Sorry but I can't do that yet. \n"); - } - - else - Help(); - - // - wprintf(L"\n"); - - - return 0; -} - -int Help (void) -{ - wprintf(L"Usage: ros-get [command] \n\n"); - - wprintf(L"Possible commands: \n"); - wprintf(L" install [package name] \t Installs a package \n\n"); - wprintf(L" show [package name] \t\t Shows you detailed information about a package \n"); - - wprintf(L"Currently unimplemented commands: \n"); - wprintf(L" src-install [package name] \t Installs a package from source code \n"); - wprintf(L" update [package name] \t Updates a package \n"); - wprintf(L" dist-update [package name] \t Updates a package \n"); - wprintf(L" remove [package name] \t Uninstalls a package \n\n"); - - wprintf(L" search [search agrument] \t Finds a package \n"); - wprintf(L" list \t\t\t\t Lists all installed programs \n"); - - return 0; -} - -int Ask (const WCHAR* question) -{ - // ask the user - wprintf(L"%s [y/n] ", question); - char answer = getchar(); - - // clear keybuffer - while(getchar()!='\n'); - wprintf(L"\n"); - - // prozess answer - if (answer == 'y') - return 1; - - else if (answer == 'n') - return 0; - - return Ask(question); -} - -int SetStatus (int status1, int status2, WCHAR* text) -{ - if(text) - wprintf(L"%s\n", text); - - // If the Status is 1000 things are done - if(status1==1000) - { - wprintf(L"%s\n", PML_TransError(status2)); - done = TRUE; - } - - return 0; -} - -int Install (void) -{ - pTree tree; - int i, error; - - // load the tree - error = PML_LoadTree (&tree, "tree.xml", NULL); - if(error) - { - wprintf(PML_TransError(error)); - return 0; - } - - // look up the item - for (i=2; i + + +int main (int argc, char **argv) +{ + wprintf(L"ReactOs PackageManager %d.%d.%d Commandline Interface \n\n", PACKMGR_VERSION_MAJOR, PACKMGR_VERSION_MINOR, PACKMGR_VERSION_PATCH_LEVEL); + Argv = argv; Argc = argc; + + if(argc<2) + return Help(); + + // install a package + if (!strcmp(argv[1], "install")) + Install(); + + // install a package from source + else if (!strcmp(argv[1], "src-inst")) + { + wprintf(L"Sorry but I can't do that yet. \n"); + } + + // update a package + else if (!strcmp(argv[1], "update")) + { + wprintf(L"Sorry but I can't do that yet. \n"); + } + + // update everything + else if (!strcmp(argv[1], "dist-upgrade")) + { + wprintf(L"Sorry but I can't do that yet. \n"); + } + + // remove a package + else if (!strcmp(argv[1], "remove")) + { + wprintf(L"Sorry but I can't do that yet. \n"); + } + + // search for a package + else if (!strcmp(argv[1], "show")) + { + Show(); + } + + // search for a package + else if (!strcmp(argv[1], "search")) + { + wprintf(L"Sorry but I can't do that yet. \n"); + } + + else + Help(); + + // + wprintf(L"\n"); + + + return 0; +} + +int Help (void) +{ + wprintf(L"Usage: ros-get [command] \n\n"); + + wprintf(L"Possible commands: \n"); + wprintf(L" install [package name] \t Installs a package \n\n"); + wprintf(L" show [package name] \t\t Shows you detailed information about a package \n"); + + wprintf(L"Currently unimplemented commands: \n"); + wprintf(L" src-install [package name] \t Installs a package from source code \n"); + wprintf(L" update [package name] \t Updates a package \n"); + wprintf(L" dist-update [package name] \t Updates a package \n"); + wprintf(L" remove [package name] \t Uninstalls a package \n\n"); + + wprintf(L" search [search agrument] \t Finds a package \n"); + wprintf(L" list \t\t\t\t Lists all installed programs \n"); + + return 0; +} + +int Ask (const WCHAR* question) +{ + // ask the user + wprintf(L"%s [y/n] ", question); + char answer = getchar(); + + // clear keybuffer + while(getchar()!='\n'); + wprintf(L"\n"); + + // prozess answer + if (answer == 'y') + return 1; + + else if (answer == 'n') + return 0; + + return Ask(question); +} + +int SetStatus (int status1, int status2, WCHAR* text) +{ + if(text) + wprintf(L"%s\n", text); + + // If the Status is 1000 things are done + if(status1==1000) + { + wprintf(L"%s\n", PML_TransError(status2)); + done = TRUE; + } + + return 0; +} + +int Install (void) +{ + pTree tree; + int i, error; + + // load the tree + error = PML_LoadTree (&tree, "tree.xml", NULL); + if(error) + { + wprintf(PML_TransError(error)); + return 0; + } + + // look up the item + for (i=2; i - -int Argc; -char **Argv; -BOOL done = FALSE; - -int Help (void); -int Install (void); -int Show (void); - -int SetStatus (int status1, int status2, WCHAR* text); +/////////////////////////////////////////////////// +// +// main.h +// main.cpp's lumber room :) +/////////////////////////////////////////////////// + +#include + +int Argc; +char **Argv; +BOOL done = FALSE; + +int Help (void); +int Install (void); +int Show (void); + +int SetStatus (int status1, int status2, WCHAR* text); diff --git a/rosapps/packmgr/gui/main.c b/rosapps/packmgr/gui/main.c index 21165aa654e..d7988289a8a 100644 --- a/rosapps/packmgr/gui/main.c +++ b/rosapps/packmgr/gui/main.c @@ -1,449 +1,449 @@ -//////////////////////////////////////////////////////// -// -// main.cpp -// -// Implementation of the Package Manager GUI -// -// -// Maarten Bosma, 09.01.2004 -// maarten.paul@bosma.de -// -//////////////////////////////////////////////////////////////////// - -#include "main.h" - -// This is the struct where the toolbar is defined -const TBBUTTON Buttons [] = -{ - {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, - - {0, 1, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // No Action - {1, 2, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Install - {2, 3, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Install from source - {3, 4, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Update - {4, 5, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Unistall - - {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, - {5, 6, TBSTATE_ENABLED, TBSTYLE_BUTTON}, // DoIt (tm) - {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, - - {6, 7, TBSTATE_ENABLED, TBSTYLE_BUTTON}, // Help - {7, 8, TBSTATE_ENABLED, TBSTYLE_BUTTON}, // Options - - {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, -}; - - -// Application's Entry Point -int WINAPI WinMain (HINSTANCE hinst, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) -{ - HWND hwnd; - MSG msg; - WNDCLASSEX wc = {0}; - - // Window creation - wc.cbSize = sizeof(WNDCLASSEX); - wc.lpszClassName = L"pgkmgr"; - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.hInstance = hinst; - wc.hIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_MAIN)); - wc.hbrBackground = (HBRUSH)(COLOR_SCROLLBAR); - - RegisterClassEx(&wc); - - hwnd = CreateWindow(L"pgkmgr", - L"ReactOS - Package Manager v0.3", - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - 500, 600, - NULL, NULL, - hinst, - NULL); - - - // Toolbar creation - InitCommonControls(); - - hTBar = CreateToolbarEx(hwnd, WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT, 0, 8, hinst, IDB_TOOLBAR, - Buttons, sizeof(Buttons)/sizeof(TBBUTTON), TBSIZE, TBSIZE, TBSIZE, TBSIZE, sizeof(TBBUTTON)); - - // Show the windows - ShowWindow(hwnd, SW_SHOW); - UpdateWindow(hwnd); - - // Load the tree - int error = PML_LoadTree(&tree, "tree.xml", AddItem); - - if(error) - { - MessageBox(0,PML_TransError(error),0,0); - return 0; - } - - // Read the help - Help(); - - // Start getting messages - while(GetMessage(&msg,NULL,0,0)) - { - if(!TranslateAccelerator(hwnd, hHotKeys, &msg)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - // Close our handle - PML_CloseTree (tree); - - return 0; -} - -// Add a item to our tree -int AddItem (int id, const char* name, int parent, int icon) -{ - TV_INSERTSTRUCT tvins; - - tvins.item.lParam = (UINT)id; - tvins.item.mask = TVIF_TEXT|TVIF_PARAM; - tvins.item.pszText = (WCHAR*)name; //that is ok - tvins.item.cchTextMax = strlen(name); - tvins.hInsertAfter = TVI_LAST; - - if(icon) - { - tvins.item.iImage = icon; - tvins.item.iSelectedImage = icon; - tvins.item.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE; - } - - if (parent==0) - tvins.hParent = TVI_ROOT; - else - tvins.hParent = nodes[parent]; - - nodes[id] = (HTREEITEM)SendMessage(hTree, TVM_INSERTITEMA, 0, (LPARAM)&tvins); - - return 0; -} - -// Load the Help from file and display it -void Help (void) -{ - int i; - char buffer [2000]; - FILE* file = fopen ("help.txt", "r"); - - if(!file) - return; - - for(i=0; i<2000; i++) - { - buffer[i] = getc(file); - if(buffer[i]==EOF) break; - } - buffer[i] = 0; - - SetText(buffer); -} - -// Create our Controls -void InitControls (HWND hwnd) -{ - - HINSTANCE hinst = GetModuleHandle(NULL); - - // Create the controls - hTree = CreateWindowEx(0, WC_TREEVIEW, L"TreeView", WS_CHILD|WS_VISIBLE|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS, - 0, 0, 0, 0, hwnd, NULL, hinst, NULL); - - hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", PML_TransError(IDS_LOAD), WS_CHILD|WS_VISIBLE|ES_MULTILINE, - 0, 0, 100, 100, hwnd, NULL, hinst, NULL); - - hPopup = LoadMenu(hinst, MAKEINTRESOURCE(IDR_POPUP)); - - // Create Tree Icons - HIMAGELIST hIcon = ImageList_Create(16,16,ILC_COLOR32,1,1); - SendMessage(hTree, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)(HIMAGELIST)hIcon); - - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(1))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(11))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(12))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(13))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(14))); - - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(2))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(3))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(4))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(5))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(6))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(7))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(8))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(9))); - ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(10))); - - // Setup Hotkeys - hHotKeys = LoadAccelerators (hinst, MAKEINTRESOURCE(IDR_HOTKEYS)); -} - -// Set the Icons -int SetIcon (int id, int icon) -{ - TVITEMEX item; - - item.hItem = nodes[id]; - item.iImage = icon; - item.iSelectedImage = icon; - item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; - - TreeView_SetItem(hTree, &item); - - return 1; -} - -// Set the Icons -int Ask (const WCHAR* message) -{ - int ans = MessageBox (0,message,0,MB_YESNO); - - if(ans == IDYES) - return 1; - - return 0; -} - -// En- or Disable a Button inside of the toolbar and the Context Menu -int SetButton (DWORD id, BOOL state) -{ - // Change the Toorbar Button - TBBUTTONINFO ti; - - ti.cbSize = sizeof (ti); - ti.dwMask = TBIF_STATE; - - if(state) - ti.fsState = TBSTATE_ENABLED; - else - ti.fsState = TBSTATE_INDETERMINATE; - - SendMessage (hTBar, TB_SETBUTTONINFO, id, (LPARAM)&ti); - - // Change the Context Menu item - MENUITEMINFO mi; - - mi.cbSize = sizeof (mi); - mi.fMask = MIIM_STATE; - - if(state) - mi.fState = MFS_ENABLED; - - else - mi.fState = MFS_GRAYED; - - SetMenuItemInfo(hPopup, id, FALSE, &mi); - - return 0; -} - -// Set the text of the text box -int SetText (const char* text) -{ - int i, j; - char buffer [2000]; - - if(!text) - return 1; - - // the windows does not need "\n" - // for new lines but "\r\n" - for(i=0,j=0; text[i]; i++,j++) - { - buffer[j] = text[i]; - if(buffer[j] == '\n') - { - buffer[j] = '\r'; - buffer[++j] = '\n'; - } - } - buffer[j] = 0; - - SetWindowTextA(hEdit, buffer); - - return 0; -} - -// Windows Message Callback (this is where most things happen) -LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - // at the very beginning ... - case WM_CREATE: - { - InitControls(hwnd); - } - break; - - // calculate the size of the controls - case WM_SIZE: - { - RECT rcl; - SendMessage(hTBar, TB_AUTOSIZE, 0L, 0L); - GetWindowRect(hTBar, &rcl); - - int win_top = rcl.bottom - rcl.top; - int win_hight = HIWORD(lParam) - win_top; - - MoveWindow(hTree, 0, win_top, LOWORD(lParam), splitter_pos*win_hight/100, TRUE); - MoveWindow(hEdit, 0, (splitter_pos*win_hight/100)+win_top, LOWORD(lParam), win_hight, TRUE); - } - break; - - // for the treeview - case WM_NOTIFY: - { - if(((LPNMHDR)lParam)->code == TVN_SELCHANGED) - { - selected = ((LPNMTREEVIEW)lParam)->itemNew.lParam; - PML_LoadPackage (tree, selected, SetButton); - SetText(PML_GetDescription (tree, selected)); - } - - else if ((int)(((LPNMHDR)lParam)->code) == NM_RCLICK) // <= aarrggg LISP - { - // which item has been click on - HTREEITEM item = TreeView_GetDropHilight(hTree); - - if(item != NULL) - { - // mark the one as seleacted - SendMessage (hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)item); - TreeView_EnsureVisible (hTree, item); - } - - // create the context menu - if(selected != 0) - { - POINT pt; - GetCursorPos (&pt); - TrackPopupMenu (GetSubMenu(hPopup, 0), 0, (UINT)pt.x, (UINT)pt.y, 0, hwnd, NULL); - } - } - } - break; - - // for the toolbar - case WM_COMMAND: - { - // All Actions - if(LOWORD(wParam) <= 5 && LOWORD(wParam) >= 1) - { - if(selected) - if(PML_SetAction(tree, selected, LOWORD(wParam)-1, SetIcon, Ask) == ERR_OK) - break; - - MessageBeep(MB_ICONHAND); - } - - // DoIt - else if(LOWORD(wParam)==6) - { - if(PML_DoIt(tree, SetStatus, Ask) == ERR_OK) - DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DOIT), hwnd, StatusProc); - else - MessageBeep(MB_ICONHAND); - } - - // Help - else if(LOWORD(wParam)==7) - Help(); - - // Options - else if(LOWORD(wParam)==8) - DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_OPTIONS), hwnd, OptionsProc); - } - break; - - // prozess hotkeys - case WM_HOTKEY: - { - if(PML_SetAction(tree, selected, wParam, SetIcon, Ask) != ERR_OK) - MessageBeep(MB_ICONHAND); - } - break; - - // ... at the very end - case WM_DESTROY: - { - PostQuitMessage(0); - return 0; - } - } - - return DefWindowProc (hwnd, message, wParam, lParam); -} - -// Warning: This function is called from another thread -int SetStatus (int status1, int status2, WCHAR* text) -{ - // Set the Rage to 1000 - SendMessage(GetDlgItem(hStatus, IDC_STATUS1), PBM_SETRANGE32, 0, 1000); - SendMessage(GetDlgItem(hStatus, IDC_STATUS2), PBM_SETRANGE32, 0, 1000); - - // The prozessbars and the text filds - if(text) - SetDlgItemText(hStatus, IDC_TSTATUS, text); - - if(status1!=-1) - SendMessage(GetDlgItem(hStatus, IDC_STATUS1), PBM_SETPOS, status1, 0); - - if(status2!=-1) - SendMessage(GetDlgItem(hStatus, IDC_STATUS2), PBM_SETPOS, status2, 0); - - // If the Status is 1000 very thing is done - if(status1==1000) - { - EndDialog(hStatus, TRUE); - MessageBox(0,PML_TransError(status2),0,0); - } - - return 0; -} - -// Callback for the Status Dialog -INT_PTR CALLBACK StatusProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_INITDIALOG: - { - hStatus = hwnd; - - } break; - - case WM_COMMAND: // can only be the about button - case WM_CLOSE: // the close-window-[x] - { - PML_Abort(); - EndDialog(hwnd, TRUE); - return 0; - } - } - - return 0; -} - -// Callback for the Options Dialog -INT_PTR CALLBACK OptionsProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_CLOSE: - EndDialog(hwnd, TRUE); - return 0; - } - - return 0; -} +//////////////////////////////////////////////////////// +// +// main.cpp +// +// Implementation of the Package Manager GUI +// +// +// Maarten Bosma, 09.01.2004 +// maarten.paul@bosma.de +// +//////////////////////////////////////////////////////////////////// + +#include "main.h" + +// This is the struct where the toolbar is defined +const TBBUTTON Buttons [] = +{ + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + + {0, 1, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // No Action + {1, 2, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Install + {2, 3, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Install from source + {3, 4, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Update + {4, 5, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON}, // Unistall + + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + {5, 6, TBSTATE_ENABLED, TBSTYLE_BUTTON}, // DoIt (tm) + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, + + {6, 7, TBSTATE_ENABLED, TBSTYLE_BUTTON}, // Help + {7, 8, TBSTATE_ENABLED, TBSTYLE_BUTTON}, // Options + + {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP}, +}; + + +// Application's Entry Point +int WINAPI WinMain (HINSTANCE hinst, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) +{ + HWND hwnd; + MSG msg; + WNDCLASSEX wc = {0}; + + // Window creation + wc.cbSize = sizeof(WNDCLASSEX); + wc.lpszClassName = L"pgkmgr"; + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)WndProc; + wc.hInstance = hinst; + wc.hIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_MAIN)); + wc.hbrBackground = (HBRUSH)(COLOR_SCROLLBAR); + + RegisterClassEx(&wc); + + hwnd = CreateWindow(L"pgkmgr", + L"ReactOS - Package Manager v0.3", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + 500, 600, + NULL, NULL, + hinst, + NULL); + + + // Toolbar creation + InitCommonControls(); + + hTBar = CreateToolbarEx(hwnd, WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT, 0, 8, hinst, IDB_TOOLBAR, + Buttons, sizeof(Buttons)/sizeof(TBBUTTON), TBSIZE, TBSIZE, TBSIZE, TBSIZE, sizeof(TBBUTTON)); + + // Show the windows + ShowWindow(hwnd, SW_SHOW); + UpdateWindow(hwnd); + + // Load the tree + int error = PML_LoadTree(&tree, "tree.xml", AddItem); + + if(error) + { + MessageBox(0,PML_TransError(error),0,0); + return 0; + } + + // Read the help + Help(); + + // Start getting messages + while(GetMessage(&msg,NULL,0,0)) + { + if(!TranslateAccelerator(hwnd, hHotKeys, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + // Close our handle + PML_CloseTree (tree); + + return 0; +} + +// Add a item to our tree +int AddItem (int id, const char* name, int parent, int icon) +{ + TV_INSERTSTRUCT tvins; + + tvins.item.lParam = (UINT)id; + tvins.item.mask = TVIF_TEXT|TVIF_PARAM; + tvins.item.pszText = (WCHAR*)name; //that is ok + tvins.item.cchTextMax = strlen(name); + tvins.hInsertAfter = TVI_LAST; + + if(icon) + { + tvins.item.iImage = icon; + tvins.item.iSelectedImage = icon; + tvins.item.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE; + } + + if (parent==0) + tvins.hParent = TVI_ROOT; + else + tvins.hParent = nodes[parent]; + + nodes[id] = (HTREEITEM)SendMessage(hTree, TVM_INSERTITEMA, 0, (LPARAM)&tvins); + + return 0; +} + +// Load the Help from file and display it +void Help (void) +{ + int i; + char buffer [2000]; + FILE* file = fopen ("help.txt", "r"); + + if(!file) + return; + + for(i=0; i<2000; i++) + { + buffer[i] = getc(file); + if(buffer[i]==EOF) break; + } + buffer[i] = 0; + + SetText(buffer); +} + +// Create our Controls +void InitControls (HWND hwnd) +{ + + HINSTANCE hinst = GetModuleHandle(NULL); + + // Create the controls + hTree = CreateWindowEx(0, WC_TREEVIEW, L"TreeView", WS_CHILD|WS_VISIBLE|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS, + 0, 0, 0, 0, hwnd, NULL, hinst, NULL); + + hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", PML_TransError(IDS_LOAD), WS_CHILD|WS_VISIBLE|ES_MULTILINE, + 0, 0, 100, 100, hwnd, NULL, hinst, NULL); + + hPopup = LoadMenu(hinst, MAKEINTRESOURCE(IDR_POPUP)); + + // Create Tree Icons + HIMAGELIST hIcon = ImageList_Create(16,16,ILC_COLOR32,1,1); + SendMessage(hTree, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)(HIMAGELIST)hIcon); + + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(1))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(11))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(12))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(13))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(14))); + + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(2))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(3))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(4))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(5))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(6))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(7))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(8))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(9))); + ImageList_AddIcon(hIcon, LoadIcon(hinst, MAKEINTRESOURCE(10))); + + // Setup Hotkeys + hHotKeys = LoadAccelerators (hinst, MAKEINTRESOURCE(IDR_HOTKEYS)); +} + +// Set the Icons +int SetIcon (int id, int icon) +{ + TVITEMEX item; + + item.hItem = nodes[id]; + item.iImage = icon; + item.iSelectedImage = icon; + item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; + + TreeView_SetItem(hTree, &item); + + return 1; +} + +// Set the Icons +int Ask (const WCHAR* message) +{ + int ans = MessageBox (0,message,0,MB_YESNO); + + if(ans == IDYES) + return 1; + + return 0; +} + +// En- or Disable a Button inside of the toolbar and the Context Menu +int SetButton (DWORD id, BOOL state) +{ + // Change the Toorbar Button + TBBUTTONINFO ti; + + ti.cbSize = sizeof (ti); + ti.dwMask = TBIF_STATE; + + if(state) + ti.fsState = TBSTATE_ENABLED; + else + ti.fsState = TBSTATE_INDETERMINATE; + + SendMessage (hTBar, TB_SETBUTTONINFO, id, (LPARAM)&ti); + + // Change the Context Menu item + MENUITEMINFO mi; + + mi.cbSize = sizeof (mi); + mi.fMask = MIIM_STATE; + + if(state) + mi.fState = MFS_ENABLED; + + else + mi.fState = MFS_GRAYED; + + SetMenuItemInfo(hPopup, id, FALSE, &mi); + + return 0; +} + +// Set the text of the text box +int SetText (const char* text) +{ + int i, j; + char buffer [2000]; + + if(!text) + return 1; + + // the windows does not need "\n" + // for new lines but "\r\n" + for(i=0,j=0; text[i]; i++,j++) + { + buffer[j] = text[i]; + if(buffer[j] == '\n') + { + buffer[j] = '\r'; + buffer[++j] = '\n'; + } + } + buffer[j] = 0; + + SetWindowTextA(hEdit, buffer); + + return 0; +} + +// Windows Message Callback (this is where most things happen) +LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + // at the very beginning ... + case WM_CREATE: + { + InitControls(hwnd); + } + break; + + // calculate the size of the controls + case WM_SIZE: + { + RECT rcl; + SendMessage(hTBar, TB_AUTOSIZE, 0L, 0L); + GetWindowRect(hTBar, &rcl); + + int win_top = rcl.bottom - rcl.top; + int win_hight = HIWORD(lParam) - win_top; + + MoveWindow(hTree, 0, win_top, LOWORD(lParam), splitter_pos*win_hight/100, TRUE); + MoveWindow(hEdit, 0, (splitter_pos*win_hight/100)+win_top, LOWORD(lParam), win_hight, TRUE); + } + break; + + // for the treeview + case WM_NOTIFY: + { + if(((LPNMHDR)lParam)->code == TVN_SELCHANGED) + { + selected = ((LPNMTREEVIEW)lParam)->itemNew.lParam; + PML_LoadPackage (tree, selected, SetButton); + SetText(PML_GetDescription (tree, selected)); + } + + else if ((int)(((LPNMHDR)lParam)->code) == NM_RCLICK) // <= aarrggg LISP + { + // which item has been click on + HTREEITEM item = TreeView_GetDropHilight(hTree); + + if(item != NULL) + { + // mark the one as seleacted + SendMessage (hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)item); + TreeView_EnsureVisible (hTree, item); + } + + // create the context menu + if(selected != 0) + { + POINT pt; + GetCursorPos (&pt); + TrackPopupMenu (GetSubMenu(hPopup, 0), 0, (UINT)pt.x, (UINT)pt.y, 0, hwnd, NULL); + } + } + } + break; + + // for the toolbar + case WM_COMMAND: + { + // All Actions + if(LOWORD(wParam) <= 5 && LOWORD(wParam) >= 1) + { + if(selected) + if(PML_SetAction(tree, selected, LOWORD(wParam)-1, SetIcon, Ask) == ERR_OK) + break; + + MessageBeep(MB_ICONHAND); + } + + // DoIt + else if(LOWORD(wParam)==6) + { + if(PML_DoIt(tree, SetStatus, Ask) == ERR_OK) + DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DOIT), hwnd, StatusProc); + else + MessageBeep(MB_ICONHAND); + } + + // Help + else if(LOWORD(wParam)==7) + Help(); + + // Options + else if(LOWORD(wParam)==8) + DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_OPTIONS), hwnd, OptionsProc); + } + break; + + // prozess hotkeys + case WM_HOTKEY: + { + if(PML_SetAction(tree, selected, wParam, SetIcon, Ask) != ERR_OK) + MessageBeep(MB_ICONHAND); + } + break; + + // ... at the very end + case WM_DESTROY: + { + PostQuitMessage(0); + return 0; + } + } + + return DefWindowProc (hwnd, message, wParam, lParam); +} + +// Warning: This function is called from another thread +int SetStatus (int status1, int status2, WCHAR* text) +{ + // Set the Rage to 1000 + SendMessage(GetDlgItem(hStatus, IDC_STATUS1), PBM_SETRANGE32, 0, 1000); + SendMessage(GetDlgItem(hStatus, IDC_STATUS2), PBM_SETRANGE32, 0, 1000); + + // The prozessbars and the text filds + if(text) + SetDlgItemText(hStatus, IDC_TSTATUS, text); + + if(status1!=-1) + SendMessage(GetDlgItem(hStatus, IDC_STATUS1), PBM_SETPOS, status1, 0); + + if(status2!=-1) + SendMessage(GetDlgItem(hStatus, IDC_STATUS2), PBM_SETPOS, status2, 0); + + // If the Status is 1000 very thing is done + if(status1==1000) + { + EndDialog(hStatus, TRUE); + MessageBox(0,PML_TransError(status2),0,0); + } + + return 0; +} + +// Callback for the Status Dialog +INT_PTR CALLBACK StatusProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + hStatus = hwnd; + + } break; + + case WM_COMMAND: // can only be the about button + case WM_CLOSE: // the close-window-[x] + { + PML_Abort(); + EndDialog(hwnd, TRUE); + return 0; + } + } + + return 0; +} + +// Callback for the Options Dialog +INT_PTR CALLBACK OptionsProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_CLOSE: + EndDialog(hwnd, TRUE); + return 0; + } + + return 0; +} diff --git a/rosapps/packmgr/gui/main.h b/rosapps/packmgr/gui/main.h index d01354cfb51..0cf522915f7 100644 --- a/rosapps/packmgr/gui/main.h +++ b/rosapps/packmgr/gui/main.h @@ -1,45 +1,45 @@ -/////////////////////////////////////////////////// -// -// main.h -// main.cpp's lumber room :) -/////////////////////////////////////////////////// - -#include -#include -#include - -#include -#include "resource.h" - -/* Some Variables */ - -int selected, splitter_pos = 50; - -pTree tree; -HMENU hPopup; -HACCEL hHotKeys; -HWND hTBar, hTree, hEdit, hStatus; -HTREEITEM nodes [MAXNODES]; - -/* Window Callbacks */ - -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); -INT_PTR CALLBACK StatusProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK OptionsProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); - -/* Prototypes */ - -void Help (void); - -int AddItem (int id, const char* name, int parent, int icon); -int SetText (const char* text); -int SetStatus (int status1, int status2, WCHAR* text); -int Ask (const WCHAR* message); - -/* Toolbar Releated */ - -#define TBSTYLE_FLAT 2048 - -// This is the struct where the toolbar is defined -extern const TBBUTTON Buttons []; - +/////////////////////////////////////////////////// +// +// main.h +// main.cpp's lumber room :) +/////////////////////////////////////////////////// + +#include +#include +#include + +#include +#include "resource.h" + +/* Some Variables */ + +int selected, splitter_pos = 50; + +pTree tree; +HMENU hPopup; +HACCEL hHotKeys; +HWND hTBar, hTree, hEdit, hStatus; +HTREEITEM nodes [MAXNODES]; + +/* Window Callbacks */ + +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK StatusProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK OptionsProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +/* Prototypes */ + +void Help (void); + +int AddItem (int id, const char* name, int parent, int icon); +int SetText (const char* text); +int SetStatus (int status1, int status2, WCHAR* text); +int Ask (const WCHAR* message); + +/* Toolbar Releated */ + +#define TBSTYLE_FLAT 2048 + +// This is the struct where the toolbar is defined +extern const TBBUTTON Buttons []; + diff --git a/rosapps/packmgr/gui/resource.h b/rosapps/packmgr/gui/resource.h index b52531ef845..8594555c4c4 100644 --- a/rosapps/packmgr/gui/resource.h +++ b/rosapps/packmgr/gui/resource.h @@ -1,15 +1,15 @@ -#include "../lib/error.h" - -#define IDI_MAIN 0 - -#define TBSIZE 32 -#define IDB_TOOLBAR 0x102 -#define IDD_OPTIONS 0x103 -#define IDD_DOIT 0x104 -#define IDR_POPUP 0x105 - -#define IDC_STATUS1 0x110 -#define IDC_STATUS2 0x111 -#define IDC_CANCEL 0x112 -#define IDC_TSTATUS 0x113 -#define IDR_HOTKEYS 0x114 +#include "../lib/error.h" + +#define IDI_MAIN 0 + +#define TBSIZE 32 +#define IDB_TOOLBAR 0x102 +#define IDD_OPTIONS 0x103 +#define IDD_DOIT 0x104 +#define IDR_POPUP 0x105 + +#define IDC_STATUS1 0x110 +#define IDC_STATUS2 0x111 +#define IDC_CANCEL 0x112 +#define IDC_TSTATUS 0x113 +#define IDR_HOTKEYS 0x114 diff --git a/rosapps/packmgr/lib/download.cpp b/rosapps/packmgr/lib/download.cpp index cf035e68973..17c447143b2 100644 --- a/rosapps/packmgr/lib/download.cpp +++ b/rosapps/packmgr/lib/download.cpp @@ -1,168 +1,168 @@ -//////////////////////////////////////////////////////// -// -// download.cpp -// -// Stuff related to downloading -// -// -// Maarten Bosma, 09.01.2004 -// maarten.paul@bosma.de -// -//////////////////////////////////////////////////////// - -#include "package.hpp" -#include "expat.h" -#include "log.h" -#include - -HRESULT WINAPI URLDownloadToFileA( - LPUNKNOWN pCaller, - LPCSTR szURL, - LPCSTR szFileName, - DWORD dwReserved, - LPBINDSTATUSCALLBACK lpfnCB -); - -int FindCount (string What, string Where, int start = 0, int end = -1); - - -// Download a file -char* PML_Download (pTree tree, const char* url, const char* server = "tree", const char* filename = "packmgr.xml") -{ - UINT i; - static char downl [MAX_PATH]; // the full url - static char path [MAX_PATH]; // the full resulting Path - - // It goes to the temp folder when no other path is entered (or even compleatly no filename) - // If server == "tree" it will be downloaded from the server speficied in option.xml - // File:// links are possible too - - // get temp dir - if(!filename) - GetTempPathA (200, path); - - else if(!strstr(filename, "\\")) - GetTempPathA (200, path); - - else - strcpy(path, ""); - - - // create the local file name - if(filename) - { - strcat(path, filename); - DeleteFileA (path); - } - else - GetTempFileNameA (path, "pml", 1, path); - - // get the url - if (!server) - strcpy(downl, ""); - - else if(!strcmp(server, "tree")) - { - char* ret; - for (i=0; isources.size(); i++) - { - ret = PML_Download(tree, url, tree->sources[i], filename); - if(ret) - return ret; - } - return NULL; - } - - else - strcpy(downl, server); - - strcat(downl, url); - - // is this a file link ? - if (strstr(downl, "file://") || strstr(downl, "File://")) - { - if(!filename) - { - return &downl[7]; - } - - else - { - CopyFileA(filename, &downl[7], FALSE); - return (char*)filename; - } - } - - - // download the file - if(URLDownloadToFileA (NULL, downl, path, 0, NULL) != S_OK) - { - Log("! ERROR: Unable to download "); - LogAdd(downl); - - return NULL; - } - - return path; -} - -// Download and prozess a xml file -int PML_XmlDownload (pTree tree, const char* url, void* usrdata, - XML_StartElementHandler start, XML_EndElementHandler end, XML_CharacterDataHandler text) -{ - int done = 0; - char buffer[255]; - char* filename = 0; - - // logging - Log("* prozess the xml file: "); - LogAdd(url); - - // download the file - if(strstr(url, "file://")) - filename = PML_Download(tree, url, NULL, NULL); - - else - filename = PML_Download(tree, url); - - - if(!filename) - { - Log("! ERROR: Could not download the xml file"); - return ERR_DOWNL; - } - - // open the file - FILE* file = fopen(filename, "r"); - if(!file) - { - Log("! ERROR: Could not open the xml file "); - LogAdd(filename); - return ERR_GENERIC; - } - - // parse the xml file - XML_Parser parser = XML_ParserCreate(NULL); - XML_SetUserData (parser, usrdata); - XML_SetElementHandler(parser, start, end); - XML_SetCharacterDataHandler(parser, text); - - while (!done) - { - size_t len = fread (buffer, 1, sizeof(buffer), file); - done = len < sizeof(buffer); - - buffer[len] = 0; - if(!XML_Parse(parser, buffer, len, done)) - { - Log("! ERROR: Could not parse the xml file"); - return ERR_GENERIC; - } - } - - XML_ParserFree(parser); - fclose(file); - - return ERR_OK; -} - +//////////////////////////////////////////////////////// +// +// download.cpp +// +// Stuff related to downloading +// +// +// Maarten Bosma, 09.01.2004 +// maarten.paul@bosma.de +// +//////////////////////////////////////////////////////// + +#include "package.hpp" +#include "expat.h" +#include "log.h" +#include + +HRESULT WINAPI URLDownloadToFileA( + LPUNKNOWN pCaller, + LPCSTR szURL, + LPCSTR szFileName, + DWORD dwReserved, + LPBINDSTATUSCALLBACK lpfnCB +); + +int FindCount (string What, string Where, int start = 0, int end = -1); + + +// Download a file +char* PML_Download (pTree tree, const char* url, const char* server = "tree", const char* filename = "packmgr.xml") +{ + UINT i; + static char downl [MAX_PATH]; // the full url + static char path [MAX_PATH]; // the full resulting Path + + // It goes to the temp folder when no other path is entered (or even compleatly no filename) + // If server == "tree" it will be downloaded from the server speficied in option.xml + // File:// links are possible too + + // get temp dir + if(!filename) + GetTempPathA (200, path); + + else if(!strstr(filename, "\\")) + GetTempPathA (200, path); + + else + strcpy(path, ""); + + + // create the local file name + if(filename) + { + strcat(path, filename); + DeleteFileA (path); + } + else + GetTempFileNameA (path, "pml", 1, path); + + // get the url + if (!server) + strcpy(downl, ""); + + else if(!strcmp(server, "tree")) + { + char* ret; + for (i=0; isources.size(); i++) + { + ret = PML_Download(tree, url, tree->sources[i], filename); + if(ret) + return ret; + } + return NULL; + } + + else + strcpy(downl, server); + + strcat(downl, url); + + // is this a file link ? + if (strstr(downl, "file://") || strstr(downl, "File://")) + { + if(!filename) + { + return &downl[7]; + } + + else + { + CopyFileA(filename, &downl[7], FALSE); + return (char*)filename; + } + } + + + // download the file + if(URLDownloadToFileA (NULL, downl, path, 0, NULL) != S_OK) + { + Log("! ERROR: Unable to download "); + LogAdd(downl); + + return NULL; + } + + return path; +} + +// Download and prozess a xml file +int PML_XmlDownload (pTree tree, const char* url, void* usrdata, + XML_StartElementHandler start, XML_EndElementHandler end, XML_CharacterDataHandler text) +{ + int done = 0; + char buffer[255]; + char* filename = 0; + + // logging + Log("* prozess the xml file: "); + LogAdd(url); + + // download the file + if(strstr(url, "file://")) + filename = PML_Download(tree, url, NULL, NULL); + + else + filename = PML_Download(tree, url); + + + if(!filename) + { + Log("! ERROR: Could not download the xml file"); + return ERR_DOWNL; + } + + // open the file + FILE* file = fopen(filename, "r"); + if(!file) + { + Log("! ERROR: Could not open the xml file "); + LogAdd(filename); + return ERR_GENERIC; + } + + // parse the xml file + XML_Parser parser = XML_ParserCreate(NULL); + XML_SetUserData (parser, usrdata); + XML_SetElementHandler(parser, start, end); + XML_SetCharacterDataHandler(parser, text); + + while (!done) + { + size_t len = fread (buffer, 1, sizeof(buffer), file); + done = len < sizeof(buffer); + + buffer[len] = 0; + if(!XML_Parse(parser, buffer, len, done)) + { + Log("! ERROR: Could not parse the xml file"); + return ERR_GENERIC; + } + } + + XML_ParserFree(parser); + fclose(file); + + return ERR_OK; +} + diff --git a/rosapps/packmgr/lib/error.h b/rosapps/packmgr/lib/error.h index ec63a7a763d..c5c6ca8c4c9 100644 --- a/rosapps/packmgr/lib/error.h +++ b/rosapps/packmgr/lib/error.h @@ -1,20 +1,20 @@ -// error.h - -#define ERR_OK 0x000 -#define ERR_GENERIC 0x001 -#define ERR_DOWNL 0x002 -#define ERR_NOTODO 0x003 // without text yet -#define ERR_PACK 0x004 - -#define ERR_DEP1 0x005 -#define ERR_DEP2 0x006 -#define ERR_READY 0x007 - -// Script -#define ERR_SYNATX 0x011 -#define ERR_CALL 0x012 -#define ERR_PARAMETER 0x013 -#define ERR_FILE 0x014 - -#define IDS_LOAD 0x254 -#define NOTFOUND -1 +// error.h + +#define ERR_OK 0x000 +#define ERR_GENERIC 0x001 +#define ERR_DOWNL 0x002 +#define ERR_NOTODO 0x003 // without text yet +#define ERR_PACK 0x004 + +#define ERR_DEP1 0x005 +#define ERR_DEP2 0x006 +#define ERR_READY 0x007 + +// Script +#define ERR_SYNATX 0x011 +#define ERR_CALL 0x012 +#define ERR_PARAMETER 0x013 +#define ERR_FILE 0x014 + +#define IDS_LOAD 0x254 +#define NOTFOUND -1 diff --git a/rosapps/packmgr/lib/expat.h b/rosapps/packmgr/lib/expat.h index c6d86a21d20..b34f94ea8dd 100644 --- a/rosapps/packmgr/lib/expat.h +++ b/rosapps/packmgr/lib/expat.h @@ -1,1081 +1,1081 @@ -/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd - See the file COPYING for copying permission. -*/ - -#ifndef XmlParse_INCLUDED -#define XmlParse_INCLUDED 1 - -#ifdef __VMS -/* 0 1 2 3 0 1 2 3 - 1234567890123456789012345678901 1234567890123456789012345678901 */ -#define XML_SetProcessingInstructionHandler XML_SetProcessingInstrHandler -#define XML_SetUnparsedEntityDeclHandler XML_SetUnparsedEntDeclHandler -#define XML_SetStartNamespaceDeclHandler XML_SetStartNamespcDeclHandler -#define XML_SetExternalEntityRefHandlerArg XML_SetExternalEntRefHandlerArg -#endif - -#include - -#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__) -#define XML_USE_MSC_EXTENSIONS 1 -#endif - -/* Expat tries very hard to make the API boundary very specifically - defined. There are two macros defined to control this boundary; - each of these can be defined before including this header to - achieve some different behavior, but doing so it not recommended or - tested frequently. - - XMLCALL - The calling convention to use for all calls across the - "library boundary." This will default to cdecl, and - try really hard to tell the compiler that's what we - want. - - XMLIMPORT - Whatever magic is needed to note that a function is - to be imported from a dynamically loaded library - (.dll, .so, or .sl, depending on your platform). - - The XMLCALL macro was added in Expat 1.95.7. The only one which is - expected to be directly useful in client code is XMLCALL. - - Note that on at least some Unix versions, the Expat library must be - compiled with the cdecl calling convention as the default since - system headers may assume the cdecl convention. -*/ -#ifndef XMLCALL -#if defined(XML_USE_MSC_EXTENSIONS) -#define XMLCALL __cdecl -#elif defined(__GNUC__) && defined(__i386) -//MF#define XMLCALL __attribute__((cdecl)) -#define XMLCALL//MF -#else -/* For any platform which uses this definition and supports more than - one calling convention, we need to extend this definition to - declare the convention used on that platform, if it's possible to - do so. - - If this is the case for your platform, please file a bug report - with information on how to identify your platform via the C - pre-processor and how to specify the same calling convention as the - platform's malloc() implementation. -*/ -#define XMLCALL -#endif -#endif /* not defined XMLCALL */ - - -#if !defined(XML_STATIC) && !defined(XMLIMPORT) -#ifndef XML_BUILDING_EXPAT -/* using Expat from an application */ - -#ifdef XML_USE_MSC_EXTENSIONS -#define XMLIMPORT __declspec(dllimport) -#endif - -#endif -#endif /* not defined XML_STATIC */ - -/* If we didn't define it above, define it away: */ -#ifndef XMLIMPORT -#define XMLIMPORT -#endif - - -#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef XML_UNICODE_WCHAR_T -#define XML_UNICODE -#endif - -struct XML_ParserStruct; -typedef struct XML_ParserStruct *XML_Parser; - -#ifdef XML_UNICODE /* Information is UTF-16 encoded. */ -#ifdef XML_UNICODE_WCHAR_T -typedef wchar_t XML_Char; -typedef wchar_t XML_LChar; -#else -typedef unsigned short XML_Char; -typedef char XML_LChar; -#endif /* XML_UNICODE_WCHAR_T */ -#else /* Information is UTF-8 encoded. */ -typedef char XML_Char; -typedef char XML_LChar; -#endif /* XML_UNICODE */ - -/* Should this be defined using stdbool.h when C99 is available? */ -typedef unsigned char XML_Bool; -#define XML_TRUE ((XML_Bool) 1) -#define XML_FALSE ((XML_Bool) 0) - -/* The XML_Status enum gives the possible return values for several - API functions. The preprocessor #defines are included so this - stanza can be added to code that still needs to support older - versions of Expat 1.95.x: - - #ifndef XML_STATUS_OK - #define XML_STATUS_OK 1 - #define XML_STATUS_ERROR 0 - #endif - - Otherwise, the #define hackery is quite ugly and would have been - dropped. -*/ -enum XML_Status { - XML_STATUS_ERROR = 0, -#define XML_STATUS_ERROR XML_STATUS_ERROR - XML_STATUS_OK = 1, -#define XML_STATUS_OK XML_STATUS_OK - XML_STATUS_SUSPENDED = 2, -#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED -}; - -enum XML_Error { - XML_ERROR_NONE, - XML_ERROR_NO_MEMORY, - XML_ERROR_SYNTAX, - XML_ERROR_NO_ELEMENTS, - XML_ERROR_INVALID_TOKEN, - XML_ERROR_UNCLOSED_TOKEN, - XML_ERROR_PARTIAL_CHAR, - XML_ERROR_TAG_MISMATCH, - XML_ERROR_DUPLICATE_ATTRIBUTE, - XML_ERROR_JUNK_AFTER_DOC_ELEMENT, - XML_ERROR_PARAM_ENTITY_REF, - XML_ERROR_UNDEFINED_ENTITY, - XML_ERROR_RECURSIVE_ENTITY_REF, - XML_ERROR_ASYNC_ENTITY, - XML_ERROR_BAD_CHAR_REF, - XML_ERROR_BINARY_ENTITY_REF, - XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, - XML_ERROR_MISPLACED_XML_PI, - XML_ERROR_UNKNOWN_ENCODING, - XML_ERROR_INCORRECT_ENCODING, - XML_ERROR_UNCLOSED_CDATA_SECTION, - XML_ERROR_EXTERNAL_ENTITY_HANDLING, - XML_ERROR_NOT_STANDALONE, - XML_ERROR_UNEXPECTED_STATE, - XML_ERROR_ENTITY_DECLARED_IN_PE, - XML_ERROR_FEATURE_REQUIRES_XML_DTD, - XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING, - XML_ERROR_UNBOUND_PREFIX, - XML_ERROR_SUSPENDED, - XML_ERROR_NOT_SUSPENDED, - XML_ERROR_ABORTED, - XML_ERROR_FINISHED, - XML_ERROR_SUSPEND_PE -}; - -enum XML_Content_Type { - XML_CTYPE_EMPTY = 1, - XML_CTYPE_ANY, - XML_CTYPE_MIXED, - XML_CTYPE_NAME, - XML_CTYPE_CHOICE, - XML_CTYPE_SEQ -}; - -enum XML_Content_Quant { - XML_CQUANT_NONE, - XML_CQUANT_OPT, - XML_CQUANT_REP, - XML_CQUANT_PLUS -}; - -/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be - XML_CQUANT_NONE, and the other fields will be zero or NULL. - If type == XML_CTYPE_MIXED, then quant will be NONE or REP and - numchildren will contain number of elements that may be mixed in - and children point to an array of XML_Content cells that will be - all of XML_CTYPE_NAME type with no quantification. - - If type == XML_CTYPE_NAME, then the name points to the name, and - the numchildren field will be zero and children will be NULL. The - quant fields indicates any quantifiers placed on the name. - - CHOICE and SEQ will have name NULL, the number of children in - numchildren and children will point, recursively, to an array - of XML_Content cells. - - The EMPTY, ANY, and MIXED types will only occur at top level. -*/ - -typedef struct XML_cp XML_Content; - -struct XML_cp { - enum XML_Content_Type type; - enum XML_Content_Quant quant; - XML_Char * name; - unsigned int numchildren; - XML_Content * children; -}; - - -/* This is called for an element declaration. See above for - description of the model argument. It's the caller's responsibility - to free model when finished with it. -*/ -typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData, - const XML_Char *name, - XML_Content *model); - -XMLPARSEAPI(void) -XML_SetElementDeclHandler(XML_Parser parser, - XML_ElementDeclHandler eldecl); - -/* The Attlist declaration handler is called for *each* attribute. So - a single Attlist declaration with multiple attributes declared will - generate multiple calls to this handler. The "default" parameter - may be NULL in the case of the "#IMPLIED" or "#REQUIRED" - keyword. The "isrequired" parameter will be true and the default - value will be NULL in the case of "#REQUIRED". If "isrequired" is - true and default is non-NULL, then this is a "#FIXED" default. -*/ -typedef void (XMLCALL *XML_AttlistDeclHandler) ( - void *userData, - const XML_Char *elname, - const XML_Char *attname, - const XML_Char *att_type, - const XML_Char *dflt, - int isrequired); - -XMLPARSEAPI(void) -XML_SetAttlistDeclHandler(XML_Parser parser, - XML_AttlistDeclHandler attdecl); - -/* The XML declaration handler is called for *both* XML declarations - and text declarations. The way to distinguish is that the version - parameter will be NULL for text declarations. The encoding - parameter may be NULL for XML declarations. The standalone - parameter will be -1, 0, or 1 indicating respectively that there - was no standalone parameter in the declaration, that it was given - as no, or that it was given as yes. -*/ -typedef void (XMLCALL *XML_XmlDeclHandler) (void *userData, - const XML_Char *version, - const XML_Char *encoding, - int standalone); - -XMLPARSEAPI(void) -XML_SetXmlDeclHandler(XML_Parser parser, - XML_XmlDeclHandler xmldecl); - - -typedef struct { - void *(XMLCALL *malloc_fcn)(size_t size); - void *(XMLCALL *realloc_fcn)(void *ptr, size_t size); - void (XMLCALL *free_fcn)(void *ptr); -} XML_Memory_Handling_Suite; - -/* Constructs a new parser; encoding is the encoding specified by the - external protocol or NULL if there is none specified. -*/ -XMLPARSEAPI(XML_Parser) -XML_ParserCreate(const XML_Char *encoding); - -/* Constructs a new parser and namespace processor. Element type - names and attribute names that belong to a namespace will be - expanded; unprefixed attribute names are never expanded; unprefixed - element type names are expanded only if there is a default - namespace. The expanded name is the concatenation of the namespace - URI, the namespace separator character, and the local part of the - name. If the namespace separator is '\0' then the namespace URI - and the local part will be concatenated without any separator. - When a namespace is not declared, the name and prefix will be - passed through without expansion. -*/ -XMLPARSEAPI(XML_Parser) -XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); - - -/* Constructs a new parser using the memory management suite referred to - by memsuite. If memsuite is NULL, then use the standard library memory - suite. If namespaceSeparator is non-NULL it creates a parser with - namespace processing as described above. The character pointed at - will serve as the namespace separator. - - All further memory operations used for the created parser will come from - the given suite. -*/ -XMLPARSEAPI(XML_Parser) -XML_ParserCreate_MM(const XML_Char *encoding, - const XML_Memory_Handling_Suite *memsuite, - const XML_Char *namespaceSeparator); - -/* Prepare a parser object to be re-used. This is particularly - valuable when memory allocation overhead is disproportionatly high, - such as when a large number of small documnents need to be parsed. - All handlers are cleared from the parser, except for the - unknownEncodingHandler. The parser's external state is re-initialized - except for the values of ns and ns_triplets. - - Added in Expat 1.95.3. -*/ -XMLPARSEAPI(XML_Bool) -XML_ParserReset(XML_Parser parser, const XML_Char *encoding); - -/* atts is array of name/value pairs, terminated by 0; - names and values are 0 terminated. -*/ -typedef void (XMLCALL *XML_StartElementHandler) (void *userData, - const XML_Char *name, - const XML_Char **atts); - -typedef void (XMLCALL *XML_EndElementHandler) (void *userData, - const XML_Char *name); - - -/* s is not 0 terminated. */ -typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData, - const XML_Char *s, - int len); - -/* target and data are 0 terminated */ -typedef void (XMLCALL *XML_ProcessingInstructionHandler) ( - void *userData, - const XML_Char *target, - const XML_Char *data); - -/* data is 0 terminated */ -typedef void (XMLCALL *XML_CommentHandler) (void *userData, - const XML_Char *data); - -typedef void (XMLCALL *XML_StartCdataSectionHandler) (void *userData); -typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData); - -/* This is called for any characters in the XML document for which - there is no applicable handler. This includes both characters that - are part of markup which is of a kind that is not reported - (comments, markup declarations), or characters that are part of a - construct which could be reported but for which no handler has been - supplied. The characters are passed exactly as they were in the XML - document except that they will be encoded in UTF-8 or UTF-16. - Line boundaries are not normalized. Note that a byte order mark - character is not passed to the default handler. There are no - guarantees about how characters are divided between calls to the - default handler: for example, a comment might be split between - multiple calls. -*/ -typedef void (XMLCALL *XML_DefaultHandler) (void *userData, - const XML_Char *s, - int len); - -/* This is called for the start of the DOCTYPE declaration, before - any DTD or internal subset is parsed. -*/ -typedef void (XMLCALL *XML_StartDoctypeDeclHandler) ( - void *userData, - const XML_Char *doctypeName, - const XML_Char *sysid, - const XML_Char *pubid, - int has_internal_subset); - -/* This is called for the start of the DOCTYPE declaration when the - closing > is encountered, but after processing any external - subset. -*/ -typedef void (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData); - -/* This is called for entity declarations. The is_parameter_entity - argument will be non-zero if the entity is a parameter entity, zero - otherwise. - - For internal entities (), value will - be non-NULL and systemId, publicID, and notationName will be NULL. - The value string is NOT nul-terminated; the length is provided in - the value_length argument. Since it is legal to have zero-length - values, do not use this argument to test for internal entities. - - For external entities, value will be NULL and systemId will be - non-NULL. The publicId argument will be NULL unless a public - identifier was provided. The notationName argument will have a - non-NULL value only for unparsed entity declarations. - - Note that is_parameter_entity can't be changed to XML_Bool, since - that would break binary compatibility. -*/ -typedef void (XMLCALL *XML_EntityDeclHandler) ( - void *userData, - const XML_Char *entityName, - int is_parameter_entity, - const XML_Char *value, - int value_length, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName); - -XMLPARSEAPI(void) -XML_SetEntityDeclHandler(XML_Parser parser, - XML_EntityDeclHandler handler); - -/* OBSOLETE -- OBSOLETE -- OBSOLETE - This handler has been superceded by the EntityDeclHandler above. - It is provided here for backward compatibility. - - This is called for a declaration of an unparsed (NDATA) entity. - The base argument is whatever was set by XML_SetBase. The - entityName, systemId and notationName arguments will never be - NULL. The other arguments may be. -*/ -typedef void (XMLCALL *XML_UnparsedEntityDeclHandler) ( - void *userData, - const XML_Char *entityName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName); - -/* This is called for a declaration of notation. The base argument is - whatever was set by XML_SetBase. The notationName will never be - NULL. The other arguments can be. -*/ -typedef void (XMLCALL *XML_NotationDeclHandler) ( - void *userData, - const XML_Char *notationName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId); - -/* When namespace processing is enabled, these are called once for - each namespace declaration. The call to the start and end element - handlers occur between the calls to the start and end namespace - declaration handlers. For an xmlns attribute, prefix will be - NULL. For an xmlns="" attribute, uri will be NULL. -*/ -typedef void (XMLCALL *XML_StartNamespaceDeclHandler) ( - void *userData, - const XML_Char *prefix, - const XML_Char *uri); - -typedef void (XMLCALL *XML_EndNamespaceDeclHandler) ( - void *userData, - const XML_Char *prefix); - -/* This is called if the document is not standalone, that is, it has an - external subset or a reference to a parameter entity, but does not - have standalone="yes". If this handler returns XML_STATUS_ERROR, - then processing will not continue, and the parser will return a - XML_ERROR_NOT_STANDALONE error. - If parameter entity parsing is enabled, then in addition to the - conditions above this handler will only be called if the referenced - entity was actually read. -*/ -typedef int (XMLCALL *XML_NotStandaloneHandler) (void *userData); - -/* This is called for a reference to an external parsed general - entity. The referenced entity is not automatically parsed. The - application can parse it immediately or later using - XML_ExternalEntityParserCreate. - - The parser argument is the parser parsing the entity containing the - reference; it can be passed as the parser argument to - XML_ExternalEntityParserCreate. The systemId argument is the - system identifier as specified in the entity declaration; it will - not be NULL. - - The base argument is the system identifier that should be used as - the base for resolving systemId if systemId was relative; this is - set by XML_SetBase; it may be NULL. - - The publicId argument is the public identifier as specified in the - entity declaration, or NULL if none was specified; the whitespace - in the public identifier will have been normalized as required by - the XML spec. - - The context argument specifies the parsing context in the format - expected by the context argument to XML_ExternalEntityParserCreate; - context is valid only until the handler returns, so if the - referenced entity is to be parsed later, it must be copied. - context is NULL only when the entity is a parameter entity. - - The handler should return XML_STATUS_ERROR if processing should not - continue because of a fatal error in the handling of the external - entity. In this case the calling parser will return an - XML_ERROR_EXTERNAL_ENTITY_HANDLING error. - - Note that unlike other handlers the first argument is the parser, - not userData. -*/ -typedef int (XMLCALL *XML_ExternalEntityRefHandler) ( - XML_Parser parser, - const XML_Char *context, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId); - -/* This is called in two situations: - 1) An entity reference is encountered for which no declaration - has been read *and* this is not an error. - 2) An internal entity reference is read, but not expanded, because - XML_SetDefaultHandler has been called. - Note: skipped parameter entities in declarations and skipped general - entities in attribute values cannot be reported, because - the event would be out of sync with the reporting of the - declarations or attribute values -*/ -typedef void (XMLCALL *XML_SkippedEntityHandler) ( - void *userData, - const XML_Char *entityName, - int is_parameter_entity); - -/* This structure is filled in by the XML_UnknownEncodingHandler to - provide information to the parser about encodings that are unknown - to the parser. - - The map[b] member gives information about byte sequences whose - first byte is b. - - If map[b] is c where c is >= 0, then b by itself encodes the - Unicode scalar value c. - - If map[b] is -1, then the byte sequence is malformed. - - If map[b] is -n, where n >= 2, then b is the first byte of an - n-byte sequence that encodes a single Unicode scalar value. - - The data member will be passed as the first argument to the convert - function. - - The convert function is used to convert multibyte sequences; s will - point to a n-byte sequence where map[(unsigned char)*s] == -n. The - convert function must return the Unicode scalar value represented - by this byte sequence or -1 if the byte sequence is malformed. - - The convert function may be NULL if the encoding is a single-byte - encoding, that is if map[b] >= -1 for all bytes b. - - When the parser is finished with the encoding, then if release is - not NULL, it will call release passing it the data member; once - release has been called, the convert function will not be called - again. - - Expat places certain restrictions on the encodings that are supported - using this mechanism. - - 1. Every ASCII character that can appear in a well-formed XML document, - other than the characters - - $@\^`{}~ - - must be represented by a single byte, and that byte must be the - same byte that represents that character in ASCII. - - 2. No character may require more than 4 bytes to encode. - - 3. All characters encoded must have Unicode scalar values <= - 0xFFFF, (i.e., characters that would be encoded by surrogates in - UTF-16 are not allowed). Note that this restriction doesn't - apply to the built-in support for UTF-8 and UTF-16. - - 4. No Unicode character may be encoded by more than one distinct - sequence of bytes. -*/ -typedef struct { - int map[256]; - void *data; - int (XMLCALL *convert)(void *data, const char *s); - void (XMLCALL *release)(void *data); -} XML_Encoding; - -/* This is called for an encoding that is unknown to the parser. - - The encodingHandlerData argument is that which was passed as the - second argument to XML_SetUnknownEncodingHandler. - - The name argument gives the name of the encoding as specified in - the encoding declaration. - - If the callback can provide information about the encoding, it must - fill in the XML_Encoding structure, and return XML_STATUS_OK. - Otherwise it must return XML_STATUS_ERROR. - - If info does not describe a suitable encoding, then the parser will - return an XML_UNKNOWN_ENCODING error. -*/ -typedef int (XMLCALL *XML_UnknownEncodingHandler) ( - void *encodingHandlerData, - const XML_Char *name, - XML_Encoding *info); - -XMLPARSEAPI(void) -XML_SetElementHandler(XML_Parser parser, - XML_StartElementHandler start, - XML_EndElementHandler end); - -XMLPARSEAPI(void) -XML_SetStartElementHandler(XML_Parser parser, - XML_StartElementHandler handler); - -XMLPARSEAPI(void) -XML_SetEndElementHandler(XML_Parser parser, - XML_EndElementHandler handler); - -XMLPARSEAPI(void) -XML_SetCharacterDataHandler(XML_Parser parser, - XML_CharacterDataHandler handler); - -XMLPARSEAPI(void) -XML_SetProcessingInstructionHandler(XML_Parser parser, - XML_ProcessingInstructionHandler handler); -XMLPARSEAPI(void) -XML_SetCommentHandler(XML_Parser parser, - XML_CommentHandler handler); - -XMLPARSEAPI(void) -XML_SetCdataSectionHandler(XML_Parser parser, - XML_StartCdataSectionHandler start, - XML_EndCdataSectionHandler end); - -XMLPARSEAPI(void) -XML_SetStartCdataSectionHandler(XML_Parser parser, - XML_StartCdataSectionHandler start); - -XMLPARSEAPI(void) -XML_SetEndCdataSectionHandler(XML_Parser parser, - XML_EndCdataSectionHandler end); - -/* This sets the default handler and also inhibits expansion of - internal entities. These entity references will be passed to the - default handler, or to the skipped entity handler, if one is set. -*/ -XMLPARSEAPI(void) -XML_SetDefaultHandler(XML_Parser parser, - XML_DefaultHandler handler); - -/* This sets the default handler but does not inhibit expansion of - internal entities. The entity reference will not be passed to the - default handler. -*/ -XMLPARSEAPI(void) -XML_SetDefaultHandlerExpand(XML_Parser parser, - XML_DefaultHandler handler); - -XMLPARSEAPI(void) -XML_SetDoctypeDeclHandler(XML_Parser parser, - XML_StartDoctypeDeclHandler start, - XML_EndDoctypeDeclHandler end); - -XMLPARSEAPI(void) -XML_SetStartDoctypeDeclHandler(XML_Parser parser, - XML_StartDoctypeDeclHandler start); - -XMLPARSEAPI(void) -XML_SetEndDoctypeDeclHandler(XML_Parser parser, - XML_EndDoctypeDeclHandler end); - -XMLPARSEAPI(void) -XML_SetUnparsedEntityDeclHandler(XML_Parser parser, - XML_UnparsedEntityDeclHandler handler); - -XMLPARSEAPI(void) -XML_SetNotationDeclHandler(XML_Parser parser, - XML_NotationDeclHandler handler); - -XMLPARSEAPI(void) -XML_SetNamespaceDeclHandler(XML_Parser parser, - XML_StartNamespaceDeclHandler start, - XML_EndNamespaceDeclHandler end); - -XMLPARSEAPI(void) -XML_SetStartNamespaceDeclHandler(XML_Parser parser, - XML_StartNamespaceDeclHandler start); - -XMLPARSEAPI(void) -XML_SetEndNamespaceDeclHandler(XML_Parser parser, - XML_EndNamespaceDeclHandler end); - -XMLPARSEAPI(void) -XML_SetNotStandaloneHandler(XML_Parser parser, - XML_NotStandaloneHandler handler); - -XMLPARSEAPI(void) -XML_SetExternalEntityRefHandler(XML_Parser parser, - XML_ExternalEntityRefHandler handler); - -/* If a non-NULL value for arg is specified here, then it will be - passed as the first argument to the external entity ref handler - instead of the parser object. -*/ -XMLPARSEAPI(void) -XML_SetExternalEntityRefHandlerArg(XML_Parser parser, - void *arg); - -XMLPARSEAPI(void) -XML_SetSkippedEntityHandler(XML_Parser parser, - XML_SkippedEntityHandler handler); - -XMLPARSEAPI(void) -XML_SetUnknownEncodingHandler(XML_Parser parser, - XML_UnknownEncodingHandler handler, - void *encodingHandlerData); - -/* This can be called within a handler for a start element, end - element, processing instruction or character data. It causes the - corresponding markup to be passed to the default handler. -*/ -XMLPARSEAPI(void) -XML_DefaultCurrent(XML_Parser parser); - -/* If do_nst is non-zero, and namespace processing is in effect, and - a name has a prefix (i.e. an explicit namespace qualifier) then - that name is returned as a triplet in a single string separated by - the separator character specified when the parser was created: URI - + sep + local_name + sep + prefix. - - If do_nst is zero, then namespace information is returned in the - default manner (URI + sep + local_name) whether or not the name - has a prefix. - - Note: Calling XML_SetReturnNSTriplet after XML_Parse or - XML_ParseBuffer has no effect. -*/ - -XMLPARSEAPI(void) -XML_SetReturnNSTriplet(XML_Parser parser, int do_nst); - -/* This value is passed as the userData argument to callbacks. */ -XMLPARSEAPI(void) -XML_SetUserData(XML_Parser parser, void *userData); - -/* Returns the last value set by XML_SetUserData or NULL. */ -#define XML_GetUserData(parser) (*(void **)(parser)) - -/* This is equivalent to supplying an encoding argument to - XML_ParserCreate. On success XML_SetEncoding returns non-zero, - zero otherwise. - Note: Calling XML_SetEncoding after XML_Parse or XML_ParseBuffer - has no effect and returns XML_STATUS_ERROR. -*/ -XMLPARSEAPI(enum XML_Status) -XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); - -/* If this function is called, then the parser will be passed as the - first argument to callbacks instead of userData. The userData will - still be accessible using XML_GetUserData. -*/ -XMLPARSEAPI(void) -XML_UseParserAsHandlerArg(XML_Parser parser); - -/* If useDTD == XML_TRUE is passed to this function, then the parser - will assume that there is an external subset, even if none is - specified in the document. In such a case the parser will call the - externalEntityRefHandler with a value of NULL for the systemId - argument (the publicId and context arguments will be NULL as well). - Note: If this function is called, then this must be done before - the first call to XML_Parse or XML_ParseBuffer, since it will - have no effect after that. Returns - XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING. - Note: If the document does not have a DOCTYPE declaration at all, - then startDoctypeDeclHandler and endDoctypeDeclHandler will not - be called, despite an external subset being parsed. - Note: If XML_DTD is not defined when Expat is compiled, returns - XML_ERROR_FEATURE_REQUIRES_XML_DTD. -*/ -XMLPARSEAPI(enum XML_Error) -XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD); - - -/* Sets the base to be used for resolving relative URIs in system - identifiers in declarations. Resolving relative identifiers is - left to the application: this value will be passed through as the - base argument to the XML_ExternalEntityRefHandler, - XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base - argument will be copied. Returns XML_STATUS_ERROR if out of memory, - XML_STATUS_OK otherwise. -*/ -XMLPARSEAPI(enum XML_Status) -XML_SetBase(XML_Parser parser, const XML_Char *base); - -XMLPARSEAPI(const XML_Char *) -XML_GetBase(XML_Parser parser); - -/* Returns the number of the attribute/value pairs passed in last call - to the XML_StartElementHandler that were specified in the start-tag - rather than defaulted. Each attribute/value pair counts as 2; thus - this correspondds to an index into the atts array passed to the - XML_StartElementHandler. -*/ -XMLPARSEAPI(int) -XML_GetSpecifiedAttributeCount(XML_Parser parser); - -/* Returns the index of the ID attribute passed in the last call to - XML_StartElementHandler, or -1 if there is no ID attribute. Each - attribute/value pair counts as 2; thus this correspondds to an - index into the atts array passed to the XML_StartElementHandler. -*/ -XMLPARSEAPI(int) -XML_GetIdAttributeIndex(XML_Parser parser); - -/* Parses some input. Returns XML_STATUS_ERROR if a fatal error is - detected. The last call to XML_Parse must have isFinal true; len - may be zero for this call (or any other). - - Though the return values for these functions has always been - described as a Boolean value, the implementation, at least for the - 1.95.x series, has always returned exactly one of the XML_Status - values. -*/ -XMLPARSEAPI(enum XML_Status) -XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); - -XMLPARSEAPI(void *) -XML_GetBuffer(XML_Parser parser, int len); - -XMLPARSEAPI(enum XML_Status) -XML_ParseBuffer(XML_Parser parser, int len, int isFinal); - -/* Stops parsing, causing XML_Parse() or XML_ParseBuffer() to return. - Must be called from within a call-back handler, except when aborting - (resumable = 0) an already suspended parser. Some call-backs may - still follow because they would otherwise get lost. Examples: - - endElementHandler() for empty elements when stopped in - startElementHandler(), - - endNameSpaceDeclHandler() when stopped in endElementHandler(), - and possibly others. - - Can be called from most handlers, including DTD related call-backs, - except when parsing an external parameter entity and resumable != 0. - Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise. - Possible error codes: - - XML_ERROR_SUSPENDED: when suspending an already suspended parser. - - XML_ERROR_FINISHED: when the parser has already finished. - - XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE. - - When resumable != 0 (true) then parsing is suspended, that is, - XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED. - Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer() - return XML_STATUS_ERROR with error code XML_ERROR_ABORTED. - - *Note*: - This will be applied to the current parser instance only, that is, if - there is a parent parser then it will continue parsing when the - externalEntityRefHandler() returns. It is up to the implementation of - the externalEntityRefHandler() to call XML_StopParser() on the parent - parser (recursively), if one wants to stop parsing altogether. - - When suspended, parsing can be resumed by calling XML_ResumeParser(). -*/ -XMLPARSEAPI(enum XML_Status) -XML_StopParser(XML_Parser parser, XML_Bool resumable); - -/* Resumes parsing after it has been suspended with XML_StopParser(). - Must not be called from within a handler call-back. Returns same - status codes as XML_Parse() or XML_ParseBuffer(). - Additional error code XML_ERROR_NOT_SUSPENDED possible. - - *Note*: - This must be called on the most deeply nested child parser instance - first, and on its parent parser only after the child parser has finished, - to be applied recursively until the document entity's parser is restarted. - That is, the parent parser will not resume by itself and it is up to the - application to call XML_ResumeParser() on it at the appropriate moment. -*/ -XMLPARSEAPI(enum XML_Status) -XML_ResumeParser(XML_Parser parser); - -enum XML_Parsing { - XML_INITIALIZED, - XML_PARSING, - XML_FINISHED, - XML_SUSPENDED -}; - -typedef struct { - enum XML_Parsing parsing; - XML_Bool finalBuffer; -} XML_ParsingStatus; - -/* Returns status of parser with respect to being initialized, parsing, - finished, or suspended and processing the final buffer. - XXX XML_Parse() and XML_ParseBuffer() should return XML_ParsingStatus, - XXX with XML_FINISHED_OK or XML_FINISHED_ERROR replacing XML_FINISHED -*/ -XMLPARSEAPI(void) -XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status); - -/* Creates an XML_Parser object that can parse an external general - entity; context is a '\0'-terminated string specifying the parse - context; encoding is a '\0'-terminated string giving the name of - the externally specified encoding, or NULL if there is no - externally specified encoding. The context string consists of a - sequence of tokens separated by formfeeds (\f); a token consisting - of a name specifies that the general entity of the name is open; a - token of the form prefix=uri specifies the namespace for a - particular prefix; a token of the form =uri specifies the default - namespace. This can be called at any point after the first call to - an ExternalEntityRefHandler so longer as the parser has not yet - been freed. The new parser is completely independent and may - safely be used in a separate thread. The handlers and userData are - initialized from the parser argument. Returns NULL if out of memory. - Otherwise returns a new XML_Parser object. -*/ -XMLPARSEAPI(XML_Parser) -XML_ExternalEntityParserCreate(XML_Parser parser, - const XML_Char *context, - const XML_Char *encoding); - -enum XML_ParamEntityParsing { - XML_PARAM_ENTITY_PARSING_NEVER, - XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, - XML_PARAM_ENTITY_PARSING_ALWAYS -}; - -/* Controls parsing of parameter entities (including the external DTD - subset). If parsing of parameter entities is enabled, then - references to external parameter entities (including the external - DTD subset) will be passed to the handler set with - XML_SetExternalEntityRefHandler. The context passed will be 0. - - Unlike external general entities, external parameter entities can - only be parsed synchronously. If the external parameter entity is - to be parsed, it must be parsed during the call to the external - entity ref handler: the complete sequence of - XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and - XML_ParserFree calls must be made during this call. After - XML_ExternalEntityParserCreate has been called to create the parser - for the external parameter entity (context must be 0 for this - call), it is illegal to make any calls on the old parser until - XML_ParserFree has been called on the newly created parser. - If the library has been compiled without support for parameter - entity parsing (ie without XML_DTD being defined), then - XML_SetParamEntityParsing will return 0 if parsing of parameter - entities is requested; otherwise it will return non-zero. - Note: If XML_SetParamEntityParsing is called after XML_Parse or - XML_ParseBuffer, then it has no effect and will always return 0. -*/ -XMLPARSEAPI(int) -XML_SetParamEntityParsing(XML_Parser parser, - enum XML_ParamEntityParsing parsing); - -/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then - XML_GetErrorCode returns information about the error. -*/ -XMLPARSEAPI(enum XML_Error) -XML_GetErrorCode(XML_Parser parser); - -/* These functions return information about the current parse - location. They may be called from any callback called to report - some parse event; in this case the location is the location of the - first of the sequence of characters that generated the event. When - called from callbacks generated by declarations in the document - prologue, the location identified isn't as neatly defined, but will - be within the relevant markup. When called outside of the callback - functions, the position indicated will be just past the last parse - event (regardless of whether there was an associated callback). - - They may also be called after returning from a call to XML_Parse - or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then - the location is the location of the character at which the error - was detected; otherwise the location is the location of the last - parse event, as described above. -*/ -XMLPARSEAPI(int) XML_GetCurrentLineNumber(XML_Parser parser); -XMLPARSEAPI(int) XML_GetCurrentColumnNumber(XML_Parser parser); -XMLPARSEAPI(long) XML_GetCurrentByteIndex(XML_Parser parser); - -/* Return the number of bytes in the current event. - Returns 0 if the event is in an internal entity. -*/ -XMLPARSEAPI(int) -XML_GetCurrentByteCount(XML_Parser parser); - -/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets - the integer pointed to by offset to the offset within this buffer - of the current parse position, and sets the integer pointed to by size - to the size of this buffer (the number of input bytes). Otherwise - returns a NULL pointer. Also returns a NULL pointer if a parse isn't - active. - - NOTE: The character pointer returned should not be used outside - the handler that makes the call. -*/ -XMLPARSEAPI(const char *) -XML_GetInputContext(XML_Parser parser, - int *offset, - int *size); - -/* For backwards compatibility with previous versions. */ -#define XML_GetErrorLineNumber XML_GetCurrentLineNumber -#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber -#define XML_GetErrorByteIndex XML_GetCurrentByteIndex - -/* Frees the content model passed to the element declaration handler */ -XMLPARSEAPI(void) -XML_FreeContentModel(XML_Parser parser, XML_Content *model); - -/* Exposing the memory handling functions used in Expat */ -XMLPARSEAPI(void *) -XML_MemMalloc(XML_Parser parser, size_t size); - -XMLPARSEAPI(void *) -XML_MemRealloc(XML_Parser parser, void *ptr, size_t size); - -XMLPARSEAPI(void) -XML_MemFree(XML_Parser parser, void *ptr); - -/* Frees memory used by the parser. */ -XMLPARSEAPI(void) -XML_ParserFree(XML_Parser parser); - -/* Returns a string describing the error. */ -XMLPARSEAPI(const XML_LChar *) -XML_ErrorString(enum XML_Error code); - -/* Return a string containing the version number of this expat */ -XMLPARSEAPI(const XML_LChar *) -XML_ExpatVersion(void); - -typedef struct { - int major; - int minor; - int micro; -} XML_Expat_Version; - -/* Return an XML_Expat_Version structure containing numeric version - number information for this version of expat. -*/ -XMLPARSEAPI(XML_Expat_Version) -XML_ExpatVersionInfo(void); - -/* Added in Expat 1.95.5. */ -enum XML_FeatureEnum { - XML_FEATURE_END = 0, - XML_FEATURE_UNICODE, - XML_FEATURE_UNICODE_WCHAR_T, - XML_FEATURE_DTD, - XML_FEATURE_CONTEXT_BYTES, - XML_FEATURE_MIN_SIZE, - XML_FEATURE_SIZEOF_XML_CHAR, - XML_FEATURE_SIZEOF_XML_LCHAR - /* Additional features must be added to the end of this enum. */ -}; - -typedef struct { - enum XML_FeatureEnum feature; - const XML_LChar *name; - long int value; -} XML_Feature; - -XMLPARSEAPI(const XML_Feature *) -XML_GetFeatureList(void); - - -/* Expat follows the GNU/Linux convention of odd number minor version for - beta/development releases and even number minor version for stable - releases. Micro is bumped with each release, and set to 0 with each - change to major or minor version. -*/ -#define XML_MAJOR_VERSION 1 -#define XML_MINOR_VERSION 95 -#define XML_MICRO_VERSION 8 - -#ifdef __cplusplus -} -#endif - -#endif /* not XmlParse_INCLUDED */ +/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#ifndef XmlParse_INCLUDED +#define XmlParse_INCLUDED 1 + +#ifdef __VMS +/* 0 1 2 3 0 1 2 3 + 1234567890123456789012345678901 1234567890123456789012345678901 */ +#define XML_SetProcessingInstructionHandler XML_SetProcessingInstrHandler +#define XML_SetUnparsedEntityDeclHandler XML_SetUnparsedEntDeclHandler +#define XML_SetStartNamespaceDeclHandler XML_SetStartNamespcDeclHandler +#define XML_SetExternalEntityRefHandlerArg XML_SetExternalEntRefHandlerArg +#endif + +#include + +#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__) +#define XML_USE_MSC_EXTENSIONS 1 +#endif + +/* Expat tries very hard to make the API boundary very specifically + defined. There are two macros defined to control this boundary; + each of these can be defined before including this header to + achieve some different behavior, but doing so it not recommended or + tested frequently. + + XMLCALL - The calling convention to use for all calls across the + "library boundary." This will default to cdecl, and + try really hard to tell the compiler that's what we + want. + + XMLIMPORT - Whatever magic is needed to note that a function is + to be imported from a dynamically loaded library + (.dll, .so, or .sl, depending on your platform). + + The XMLCALL macro was added in Expat 1.95.7. The only one which is + expected to be directly useful in client code is XMLCALL. + + Note that on at least some Unix versions, the Expat library must be + compiled with the cdecl calling convention as the default since + system headers may assume the cdecl convention. +*/ +#ifndef XMLCALL +#if defined(XML_USE_MSC_EXTENSIONS) +#define XMLCALL __cdecl +#elif defined(__GNUC__) && defined(__i386) +//MF#define XMLCALL __attribute__((cdecl)) +#define XMLCALL//MF +#else +/* For any platform which uses this definition and supports more than + one calling convention, we need to extend this definition to + declare the convention used on that platform, if it's possible to + do so. + + If this is the case for your platform, please file a bug report + with information on how to identify your platform via the C + pre-processor and how to specify the same calling convention as the + platform's malloc() implementation. +*/ +#define XMLCALL +#endif +#endif /* not defined XMLCALL */ + + +#if !defined(XML_STATIC) && !defined(XMLIMPORT) +#ifndef XML_BUILDING_EXPAT +/* using Expat from an application */ + +#ifdef XML_USE_MSC_EXTENSIONS +#define XMLIMPORT __declspec(dllimport) +#endif + +#endif +#endif /* not defined XML_STATIC */ + +/* If we didn't define it above, define it away: */ +#ifndef XMLIMPORT +#define XMLIMPORT +#endif + + +#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef XML_UNICODE_WCHAR_T +#define XML_UNICODE +#endif + +struct XML_ParserStruct; +typedef struct XML_ParserStruct *XML_Parser; + +#ifdef XML_UNICODE /* Information is UTF-16 encoded. */ +#ifdef XML_UNICODE_WCHAR_T +typedef wchar_t XML_Char; +typedef wchar_t XML_LChar; +#else +typedef unsigned short XML_Char; +typedef char XML_LChar; +#endif /* XML_UNICODE_WCHAR_T */ +#else /* Information is UTF-8 encoded. */ +typedef char XML_Char; +typedef char XML_LChar; +#endif /* XML_UNICODE */ + +/* Should this be defined using stdbool.h when C99 is available? */ +typedef unsigned char XML_Bool; +#define XML_TRUE ((XML_Bool) 1) +#define XML_FALSE ((XML_Bool) 0) + +/* The XML_Status enum gives the possible return values for several + API functions. The preprocessor #defines are included so this + stanza can be added to code that still needs to support older + versions of Expat 1.95.x: + + #ifndef XML_STATUS_OK + #define XML_STATUS_OK 1 + #define XML_STATUS_ERROR 0 + #endif + + Otherwise, the #define hackery is quite ugly and would have been + dropped. +*/ +enum XML_Status { + XML_STATUS_ERROR = 0, +#define XML_STATUS_ERROR XML_STATUS_ERROR + XML_STATUS_OK = 1, +#define XML_STATUS_OK XML_STATUS_OK + XML_STATUS_SUSPENDED = 2, +#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED +}; + +enum XML_Error { + XML_ERROR_NONE, + XML_ERROR_NO_MEMORY, + XML_ERROR_SYNTAX, + XML_ERROR_NO_ELEMENTS, + XML_ERROR_INVALID_TOKEN, + XML_ERROR_UNCLOSED_TOKEN, + XML_ERROR_PARTIAL_CHAR, + XML_ERROR_TAG_MISMATCH, + XML_ERROR_DUPLICATE_ATTRIBUTE, + XML_ERROR_JUNK_AFTER_DOC_ELEMENT, + XML_ERROR_PARAM_ENTITY_REF, + XML_ERROR_UNDEFINED_ENTITY, + XML_ERROR_RECURSIVE_ENTITY_REF, + XML_ERROR_ASYNC_ENTITY, + XML_ERROR_BAD_CHAR_REF, + XML_ERROR_BINARY_ENTITY_REF, + XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, + XML_ERROR_MISPLACED_XML_PI, + XML_ERROR_UNKNOWN_ENCODING, + XML_ERROR_INCORRECT_ENCODING, + XML_ERROR_UNCLOSED_CDATA_SECTION, + XML_ERROR_EXTERNAL_ENTITY_HANDLING, + XML_ERROR_NOT_STANDALONE, + XML_ERROR_UNEXPECTED_STATE, + XML_ERROR_ENTITY_DECLARED_IN_PE, + XML_ERROR_FEATURE_REQUIRES_XML_DTD, + XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING, + XML_ERROR_UNBOUND_PREFIX, + XML_ERROR_SUSPENDED, + XML_ERROR_NOT_SUSPENDED, + XML_ERROR_ABORTED, + XML_ERROR_FINISHED, + XML_ERROR_SUSPEND_PE +}; + +enum XML_Content_Type { + XML_CTYPE_EMPTY = 1, + XML_CTYPE_ANY, + XML_CTYPE_MIXED, + XML_CTYPE_NAME, + XML_CTYPE_CHOICE, + XML_CTYPE_SEQ +}; + +enum XML_Content_Quant { + XML_CQUANT_NONE, + XML_CQUANT_OPT, + XML_CQUANT_REP, + XML_CQUANT_PLUS +}; + +/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be + XML_CQUANT_NONE, and the other fields will be zero or NULL. + If type == XML_CTYPE_MIXED, then quant will be NONE or REP and + numchildren will contain number of elements that may be mixed in + and children point to an array of XML_Content cells that will be + all of XML_CTYPE_NAME type with no quantification. + + If type == XML_CTYPE_NAME, then the name points to the name, and + the numchildren field will be zero and children will be NULL. The + quant fields indicates any quantifiers placed on the name. + + CHOICE and SEQ will have name NULL, the number of children in + numchildren and children will point, recursively, to an array + of XML_Content cells. + + The EMPTY, ANY, and MIXED types will only occur at top level. +*/ + +typedef struct XML_cp XML_Content; + +struct XML_cp { + enum XML_Content_Type type; + enum XML_Content_Quant quant; + XML_Char * name; + unsigned int numchildren; + XML_Content * children; +}; + + +/* This is called for an element declaration. See above for + description of the model argument. It's the caller's responsibility + to free model when finished with it. +*/ +typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData, + const XML_Char *name, + XML_Content *model); + +XMLPARSEAPI(void) +XML_SetElementDeclHandler(XML_Parser parser, + XML_ElementDeclHandler eldecl); + +/* The Attlist declaration handler is called for *each* attribute. So + a single Attlist declaration with multiple attributes declared will + generate multiple calls to this handler. The "default" parameter + may be NULL in the case of the "#IMPLIED" or "#REQUIRED" + keyword. The "isrequired" parameter will be true and the default + value will be NULL in the case of "#REQUIRED". If "isrequired" is + true and default is non-NULL, then this is a "#FIXED" default. +*/ +typedef void (XMLCALL *XML_AttlistDeclHandler) ( + void *userData, + const XML_Char *elname, + const XML_Char *attname, + const XML_Char *att_type, + const XML_Char *dflt, + int isrequired); + +XMLPARSEAPI(void) +XML_SetAttlistDeclHandler(XML_Parser parser, + XML_AttlistDeclHandler attdecl); + +/* The XML declaration handler is called for *both* XML declarations + and text declarations. The way to distinguish is that the version + parameter will be NULL for text declarations. The encoding + parameter may be NULL for XML declarations. The standalone + parameter will be -1, 0, or 1 indicating respectively that there + was no standalone parameter in the declaration, that it was given + as no, or that it was given as yes. +*/ +typedef void (XMLCALL *XML_XmlDeclHandler) (void *userData, + const XML_Char *version, + const XML_Char *encoding, + int standalone); + +XMLPARSEAPI(void) +XML_SetXmlDeclHandler(XML_Parser parser, + XML_XmlDeclHandler xmldecl); + + +typedef struct { + void *(XMLCALL *malloc_fcn)(size_t size); + void *(XMLCALL *realloc_fcn)(void *ptr, size_t size); + void (XMLCALL *free_fcn)(void *ptr); +} XML_Memory_Handling_Suite; + +/* Constructs a new parser; encoding is the encoding specified by the + external protocol or NULL if there is none specified. +*/ +XMLPARSEAPI(XML_Parser) +XML_ParserCreate(const XML_Char *encoding); + +/* Constructs a new parser and namespace processor. Element type + names and attribute names that belong to a namespace will be + expanded; unprefixed attribute names are never expanded; unprefixed + element type names are expanded only if there is a default + namespace. The expanded name is the concatenation of the namespace + URI, the namespace separator character, and the local part of the + name. If the namespace separator is '\0' then the namespace URI + and the local part will be concatenated without any separator. + When a namespace is not declared, the name and prefix will be + passed through without expansion. +*/ +XMLPARSEAPI(XML_Parser) +XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); + + +/* Constructs a new parser using the memory management suite referred to + by memsuite. If memsuite is NULL, then use the standard library memory + suite. If namespaceSeparator is non-NULL it creates a parser with + namespace processing as described above. The character pointed at + will serve as the namespace separator. + + All further memory operations used for the created parser will come from + the given suite. +*/ +XMLPARSEAPI(XML_Parser) +XML_ParserCreate_MM(const XML_Char *encoding, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *namespaceSeparator); + +/* Prepare a parser object to be re-used. This is particularly + valuable when memory allocation overhead is disproportionatly high, + such as when a large number of small documnents need to be parsed. + All handlers are cleared from the parser, except for the + unknownEncodingHandler. The parser's external state is re-initialized + except for the values of ns and ns_triplets. + + Added in Expat 1.95.3. +*/ +XMLPARSEAPI(XML_Bool) +XML_ParserReset(XML_Parser parser, const XML_Char *encoding); + +/* atts is array of name/value pairs, terminated by 0; + names and values are 0 terminated. +*/ +typedef void (XMLCALL *XML_StartElementHandler) (void *userData, + const XML_Char *name, + const XML_Char **atts); + +typedef void (XMLCALL *XML_EndElementHandler) (void *userData, + const XML_Char *name); + + +/* s is not 0 terminated. */ +typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData, + const XML_Char *s, + int len); + +/* target and data are 0 terminated */ +typedef void (XMLCALL *XML_ProcessingInstructionHandler) ( + void *userData, + const XML_Char *target, + const XML_Char *data); + +/* data is 0 terminated */ +typedef void (XMLCALL *XML_CommentHandler) (void *userData, + const XML_Char *data); + +typedef void (XMLCALL *XML_StartCdataSectionHandler) (void *userData); +typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData); + +/* This is called for any characters in the XML document for which + there is no applicable handler. This includes both characters that + are part of markup which is of a kind that is not reported + (comments, markup declarations), or characters that are part of a + construct which could be reported but for which no handler has been + supplied. The characters are passed exactly as they were in the XML + document except that they will be encoded in UTF-8 or UTF-16. + Line boundaries are not normalized. Note that a byte order mark + character is not passed to the default handler. There are no + guarantees about how characters are divided between calls to the + default handler: for example, a comment might be split between + multiple calls. +*/ +typedef void (XMLCALL *XML_DefaultHandler) (void *userData, + const XML_Char *s, + int len); + +/* This is called for the start of the DOCTYPE declaration, before + any DTD or internal subset is parsed. +*/ +typedef void (XMLCALL *XML_StartDoctypeDeclHandler) ( + void *userData, + const XML_Char *doctypeName, + const XML_Char *sysid, + const XML_Char *pubid, + int has_internal_subset); + +/* This is called for the start of the DOCTYPE declaration when the + closing > is encountered, but after processing any external + subset. +*/ +typedef void (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData); + +/* This is called for entity declarations. The is_parameter_entity + argument will be non-zero if the entity is a parameter entity, zero + otherwise. + + For internal entities (), value will + be non-NULL and systemId, publicID, and notationName will be NULL. + The value string is NOT nul-terminated; the length is provided in + the value_length argument. Since it is legal to have zero-length + values, do not use this argument to test for internal entities. + + For external entities, value will be NULL and systemId will be + non-NULL. The publicId argument will be NULL unless a public + identifier was provided. The notationName argument will have a + non-NULL value only for unparsed entity declarations. + + Note that is_parameter_entity can't be changed to XML_Bool, since + that would break binary compatibility. +*/ +typedef void (XMLCALL *XML_EntityDeclHandler) ( + void *userData, + const XML_Char *entityName, + int is_parameter_entity, + const XML_Char *value, + int value_length, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); + +XMLPARSEAPI(void) +XML_SetEntityDeclHandler(XML_Parser parser, + XML_EntityDeclHandler handler); + +/* OBSOLETE -- OBSOLETE -- OBSOLETE + This handler has been superceded by the EntityDeclHandler above. + It is provided here for backward compatibility. + + This is called for a declaration of an unparsed (NDATA) entity. + The base argument is whatever was set by XML_SetBase. The + entityName, systemId and notationName arguments will never be + NULL. The other arguments may be. +*/ +typedef void (XMLCALL *XML_UnparsedEntityDeclHandler) ( + void *userData, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); + +/* This is called for a declaration of notation. The base argument is + whatever was set by XML_SetBase. The notationName will never be + NULL. The other arguments can be. +*/ +typedef void (XMLCALL *XML_NotationDeclHandler) ( + void *userData, + const XML_Char *notationName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +/* When namespace processing is enabled, these are called once for + each namespace declaration. The call to the start and end element + handlers occur between the calls to the start and end namespace + declaration handlers. For an xmlns attribute, prefix will be + NULL. For an xmlns="" attribute, uri will be NULL. +*/ +typedef void (XMLCALL *XML_StartNamespaceDeclHandler) ( + void *userData, + const XML_Char *prefix, + const XML_Char *uri); + +typedef void (XMLCALL *XML_EndNamespaceDeclHandler) ( + void *userData, + const XML_Char *prefix); + +/* This is called if the document is not standalone, that is, it has an + external subset or a reference to a parameter entity, but does not + have standalone="yes". If this handler returns XML_STATUS_ERROR, + then processing will not continue, and the parser will return a + XML_ERROR_NOT_STANDALONE error. + If parameter entity parsing is enabled, then in addition to the + conditions above this handler will only be called if the referenced + entity was actually read. +*/ +typedef int (XMLCALL *XML_NotStandaloneHandler) (void *userData); + +/* This is called for a reference to an external parsed general + entity. The referenced entity is not automatically parsed. The + application can parse it immediately or later using + XML_ExternalEntityParserCreate. + + The parser argument is the parser parsing the entity containing the + reference; it can be passed as the parser argument to + XML_ExternalEntityParserCreate. The systemId argument is the + system identifier as specified in the entity declaration; it will + not be NULL. + + The base argument is the system identifier that should be used as + the base for resolving systemId if systemId was relative; this is + set by XML_SetBase; it may be NULL. + + The publicId argument is the public identifier as specified in the + entity declaration, or NULL if none was specified; the whitespace + in the public identifier will have been normalized as required by + the XML spec. + + The context argument specifies the parsing context in the format + expected by the context argument to XML_ExternalEntityParserCreate; + context is valid only until the handler returns, so if the + referenced entity is to be parsed later, it must be copied. + context is NULL only when the entity is a parameter entity. + + The handler should return XML_STATUS_ERROR if processing should not + continue because of a fatal error in the handling of the external + entity. In this case the calling parser will return an + XML_ERROR_EXTERNAL_ENTITY_HANDLING error. + + Note that unlike other handlers the first argument is the parser, + not userData. +*/ +typedef int (XMLCALL *XML_ExternalEntityRefHandler) ( + XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +/* This is called in two situations: + 1) An entity reference is encountered for which no declaration + has been read *and* this is not an error. + 2) An internal entity reference is read, but not expanded, because + XML_SetDefaultHandler has been called. + Note: skipped parameter entities in declarations and skipped general + entities in attribute values cannot be reported, because + the event would be out of sync with the reporting of the + declarations or attribute values +*/ +typedef void (XMLCALL *XML_SkippedEntityHandler) ( + void *userData, + const XML_Char *entityName, + int is_parameter_entity); + +/* This structure is filled in by the XML_UnknownEncodingHandler to + provide information to the parser about encodings that are unknown + to the parser. + + The map[b] member gives information about byte sequences whose + first byte is b. + + If map[b] is c where c is >= 0, then b by itself encodes the + Unicode scalar value c. + + If map[b] is -1, then the byte sequence is malformed. + + If map[b] is -n, where n >= 2, then b is the first byte of an + n-byte sequence that encodes a single Unicode scalar value. + + The data member will be passed as the first argument to the convert + function. + + The convert function is used to convert multibyte sequences; s will + point to a n-byte sequence where map[(unsigned char)*s] == -n. The + convert function must return the Unicode scalar value represented + by this byte sequence or -1 if the byte sequence is malformed. + + The convert function may be NULL if the encoding is a single-byte + encoding, that is if map[b] >= -1 for all bytes b. + + When the parser is finished with the encoding, then if release is + not NULL, it will call release passing it the data member; once + release has been called, the convert function will not be called + again. + + Expat places certain restrictions on the encodings that are supported + using this mechanism. + + 1. Every ASCII character that can appear in a well-formed XML document, + other than the characters + + $@\^`{}~ + + must be represented by a single byte, and that byte must be the + same byte that represents that character in ASCII. + + 2. No character may require more than 4 bytes to encode. + + 3. All characters encoded must have Unicode scalar values <= + 0xFFFF, (i.e., characters that would be encoded by surrogates in + UTF-16 are not allowed). Note that this restriction doesn't + apply to the built-in support for UTF-8 and UTF-16. + + 4. No Unicode character may be encoded by more than one distinct + sequence of bytes. +*/ +typedef struct { + int map[256]; + void *data; + int (XMLCALL *convert)(void *data, const char *s); + void (XMLCALL *release)(void *data); +} XML_Encoding; + +/* This is called for an encoding that is unknown to the parser. + + The encodingHandlerData argument is that which was passed as the + second argument to XML_SetUnknownEncodingHandler. + + The name argument gives the name of the encoding as specified in + the encoding declaration. + + If the callback can provide information about the encoding, it must + fill in the XML_Encoding structure, and return XML_STATUS_OK. + Otherwise it must return XML_STATUS_ERROR. + + If info does not describe a suitable encoding, then the parser will + return an XML_UNKNOWN_ENCODING error. +*/ +typedef int (XMLCALL *XML_UnknownEncodingHandler) ( + void *encodingHandlerData, + const XML_Char *name, + XML_Encoding *info); + +XMLPARSEAPI(void) +XML_SetElementHandler(XML_Parser parser, + XML_StartElementHandler start, + XML_EndElementHandler end); + +XMLPARSEAPI(void) +XML_SetStartElementHandler(XML_Parser parser, + XML_StartElementHandler handler); + +XMLPARSEAPI(void) +XML_SetEndElementHandler(XML_Parser parser, + XML_EndElementHandler handler); + +XMLPARSEAPI(void) +XML_SetCharacterDataHandler(XML_Parser parser, + XML_CharacterDataHandler handler); + +XMLPARSEAPI(void) +XML_SetProcessingInstructionHandler(XML_Parser parser, + XML_ProcessingInstructionHandler handler); +XMLPARSEAPI(void) +XML_SetCommentHandler(XML_Parser parser, + XML_CommentHandler handler); + +XMLPARSEAPI(void) +XML_SetCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start, + XML_EndCdataSectionHandler end); + +XMLPARSEAPI(void) +XML_SetStartCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start); + +XMLPARSEAPI(void) +XML_SetEndCdataSectionHandler(XML_Parser parser, + XML_EndCdataSectionHandler end); + +/* This sets the default handler and also inhibits expansion of + internal entities. These entity references will be passed to the + default handler, or to the skipped entity handler, if one is set. +*/ +XMLPARSEAPI(void) +XML_SetDefaultHandler(XML_Parser parser, + XML_DefaultHandler handler); + +/* This sets the default handler but does not inhibit expansion of + internal entities. The entity reference will not be passed to the + default handler. +*/ +XMLPARSEAPI(void) +XML_SetDefaultHandlerExpand(XML_Parser parser, + XML_DefaultHandler handler); + +XMLPARSEAPI(void) +XML_SetDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start, + XML_EndDoctypeDeclHandler end); + +XMLPARSEAPI(void) +XML_SetStartDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start); + +XMLPARSEAPI(void) +XML_SetEndDoctypeDeclHandler(XML_Parser parser, + XML_EndDoctypeDeclHandler end); + +XMLPARSEAPI(void) +XML_SetUnparsedEntityDeclHandler(XML_Parser parser, + XML_UnparsedEntityDeclHandler handler); + +XMLPARSEAPI(void) +XML_SetNotationDeclHandler(XML_Parser parser, + XML_NotationDeclHandler handler); + +XMLPARSEAPI(void) +XML_SetNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start, + XML_EndNamespaceDeclHandler end); + +XMLPARSEAPI(void) +XML_SetStartNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start); + +XMLPARSEAPI(void) +XML_SetEndNamespaceDeclHandler(XML_Parser parser, + XML_EndNamespaceDeclHandler end); + +XMLPARSEAPI(void) +XML_SetNotStandaloneHandler(XML_Parser parser, + XML_NotStandaloneHandler handler); + +XMLPARSEAPI(void) +XML_SetExternalEntityRefHandler(XML_Parser parser, + XML_ExternalEntityRefHandler handler); + +/* If a non-NULL value for arg is specified here, then it will be + passed as the first argument to the external entity ref handler + instead of the parser object. +*/ +XMLPARSEAPI(void) +XML_SetExternalEntityRefHandlerArg(XML_Parser parser, + void *arg); + +XMLPARSEAPI(void) +XML_SetSkippedEntityHandler(XML_Parser parser, + XML_SkippedEntityHandler handler); + +XMLPARSEAPI(void) +XML_SetUnknownEncodingHandler(XML_Parser parser, + XML_UnknownEncodingHandler handler, + void *encodingHandlerData); + +/* This can be called within a handler for a start element, end + element, processing instruction or character data. It causes the + corresponding markup to be passed to the default handler. +*/ +XMLPARSEAPI(void) +XML_DefaultCurrent(XML_Parser parser); + +/* If do_nst is non-zero, and namespace processing is in effect, and + a name has a prefix (i.e. an explicit namespace qualifier) then + that name is returned as a triplet in a single string separated by + the separator character specified when the parser was created: URI + + sep + local_name + sep + prefix. + + If do_nst is zero, then namespace information is returned in the + default manner (URI + sep + local_name) whether or not the name + has a prefix. + + Note: Calling XML_SetReturnNSTriplet after XML_Parse or + XML_ParseBuffer has no effect. +*/ + +XMLPARSEAPI(void) +XML_SetReturnNSTriplet(XML_Parser parser, int do_nst); + +/* This value is passed as the userData argument to callbacks. */ +XMLPARSEAPI(void) +XML_SetUserData(XML_Parser parser, void *userData); + +/* Returns the last value set by XML_SetUserData or NULL. */ +#define XML_GetUserData(parser) (*(void **)(parser)) + +/* This is equivalent to supplying an encoding argument to + XML_ParserCreate. On success XML_SetEncoding returns non-zero, + zero otherwise. + Note: Calling XML_SetEncoding after XML_Parse or XML_ParseBuffer + has no effect and returns XML_STATUS_ERROR. +*/ +XMLPARSEAPI(enum XML_Status) +XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); + +/* If this function is called, then the parser will be passed as the + first argument to callbacks instead of userData. The userData will + still be accessible using XML_GetUserData. +*/ +XMLPARSEAPI(void) +XML_UseParserAsHandlerArg(XML_Parser parser); + +/* If useDTD == XML_TRUE is passed to this function, then the parser + will assume that there is an external subset, even if none is + specified in the document. In such a case the parser will call the + externalEntityRefHandler with a value of NULL for the systemId + argument (the publicId and context arguments will be NULL as well). + Note: If this function is called, then this must be done before + the first call to XML_Parse or XML_ParseBuffer, since it will + have no effect after that. Returns + XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING. + Note: If the document does not have a DOCTYPE declaration at all, + then startDoctypeDeclHandler and endDoctypeDeclHandler will not + be called, despite an external subset being parsed. + Note: If XML_DTD is not defined when Expat is compiled, returns + XML_ERROR_FEATURE_REQUIRES_XML_DTD. +*/ +XMLPARSEAPI(enum XML_Error) +XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD); + + +/* Sets the base to be used for resolving relative URIs in system + identifiers in declarations. Resolving relative identifiers is + left to the application: this value will be passed through as the + base argument to the XML_ExternalEntityRefHandler, + XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base + argument will be copied. Returns XML_STATUS_ERROR if out of memory, + XML_STATUS_OK otherwise. +*/ +XMLPARSEAPI(enum XML_Status) +XML_SetBase(XML_Parser parser, const XML_Char *base); + +XMLPARSEAPI(const XML_Char *) +XML_GetBase(XML_Parser parser); + +/* Returns the number of the attribute/value pairs passed in last call + to the XML_StartElementHandler that were specified in the start-tag + rather than defaulted. Each attribute/value pair counts as 2; thus + this correspondds to an index into the atts array passed to the + XML_StartElementHandler. +*/ +XMLPARSEAPI(int) +XML_GetSpecifiedAttributeCount(XML_Parser parser); + +/* Returns the index of the ID attribute passed in the last call to + XML_StartElementHandler, or -1 if there is no ID attribute. Each + attribute/value pair counts as 2; thus this correspondds to an + index into the atts array passed to the XML_StartElementHandler. +*/ +XMLPARSEAPI(int) +XML_GetIdAttributeIndex(XML_Parser parser); + +/* Parses some input. Returns XML_STATUS_ERROR if a fatal error is + detected. The last call to XML_Parse must have isFinal true; len + may be zero for this call (or any other). + + Though the return values for these functions has always been + described as a Boolean value, the implementation, at least for the + 1.95.x series, has always returned exactly one of the XML_Status + values. +*/ +XMLPARSEAPI(enum XML_Status) +XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); + +XMLPARSEAPI(void *) +XML_GetBuffer(XML_Parser parser, int len); + +XMLPARSEAPI(enum XML_Status) +XML_ParseBuffer(XML_Parser parser, int len, int isFinal); + +/* Stops parsing, causing XML_Parse() or XML_ParseBuffer() to return. + Must be called from within a call-back handler, except when aborting + (resumable = 0) an already suspended parser. Some call-backs may + still follow because they would otherwise get lost. Examples: + - endElementHandler() for empty elements when stopped in + startElementHandler(), + - endNameSpaceDeclHandler() when stopped in endElementHandler(), + and possibly others. + + Can be called from most handlers, including DTD related call-backs, + except when parsing an external parameter entity and resumable != 0. + Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise. + Possible error codes: + - XML_ERROR_SUSPENDED: when suspending an already suspended parser. + - XML_ERROR_FINISHED: when the parser has already finished. + - XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE. + + When resumable != 0 (true) then parsing is suspended, that is, + XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED. + Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer() + return XML_STATUS_ERROR with error code XML_ERROR_ABORTED. + + *Note*: + This will be applied to the current parser instance only, that is, if + there is a parent parser then it will continue parsing when the + externalEntityRefHandler() returns. It is up to the implementation of + the externalEntityRefHandler() to call XML_StopParser() on the parent + parser (recursively), if one wants to stop parsing altogether. + + When suspended, parsing can be resumed by calling XML_ResumeParser(). +*/ +XMLPARSEAPI(enum XML_Status) +XML_StopParser(XML_Parser parser, XML_Bool resumable); + +/* Resumes parsing after it has been suspended with XML_StopParser(). + Must not be called from within a handler call-back. Returns same + status codes as XML_Parse() or XML_ParseBuffer(). + Additional error code XML_ERROR_NOT_SUSPENDED possible. + + *Note*: + This must be called on the most deeply nested child parser instance + first, and on its parent parser only after the child parser has finished, + to be applied recursively until the document entity's parser is restarted. + That is, the parent parser will not resume by itself and it is up to the + application to call XML_ResumeParser() on it at the appropriate moment. +*/ +XMLPARSEAPI(enum XML_Status) +XML_ResumeParser(XML_Parser parser); + +enum XML_Parsing { + XML_INITIALIZED, + XML_PARSING, + XML_FINISHED, + XML_SUSPENDED +}; + +typedef struct { + enum XML_Parsing parsing; + XML_Bool finalBuffer; +} XML_ParsingStatus; + +/* Returns status of parser with respect to being initialized, parsing, + finished, or suspended and processing the final buffer. + XXX XML_Parse() and XML_ParseBuffer() should return XML_ParsingStatus, + XXX with XML_FINISHED_OK or XML_FINISHED_ERROR replacing XML_FINISHED +*/ +XMLPARSEAPI(void) +XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status); + +/* Creates an XML_Parser object that can parse an external general + entity; context is a '\0'-terminated string specifying the parse + context; encoding is a '\0'-terminated string giving the name of + the externally specified encoding, or NULL if there is no + externally specified encoding. The context string consists of a + sequence of tokens separated by formfeeds (\f); a token consisting + of a name specifies that the general entity of the name is open; a + token of the form prefix=uri specifies the namespace for a + particular prefix; a token of the form =uri specifies the default + namespace. This can be called at any point after the first call to + an ExternalEntityRefHandler so longer as the parser has not yet + been freed. The new parser is completely independent and may + safely be used in a separate thread. The handlers and userData are + initialized from the parser argument. Returns NULL if out of memory. + Otherwise returns a new XML_Parser object. +*/ +XMLPARSEAPI(XML_Parser) +XML_ExternalEntityParserCreate(XML_Parser parser, + const XML_Char *context, + const XML_Char *encoding); + +enum XML_ParamEntityParsing { + XML_PARAM_ENTITY_PARSING_NEVER, + XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, + XML_PARAM_ENTITY_PARSING_ALWAYS +}; + +/* Controls parsing of parameter entities (including the external DTD + subset). If parsing of parameter entities is enabled, then + references to external parameter entities (including the external + DTD subset) will be passed to the handler set with + XML_SetExternalEntityRefHandler. The context passed will be 0. + + Unlike external general entities, external parameter entities can + only be parsed synchronously. If the external parameter entity is + to be parsed, it must be parsed during the call to the external + entity ref handler: the complete sequence of + XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and + XML_ParserFree calls must be made during this call. After + XML_ExternalEntityParserCreate has been called to create the parser + for the external parameter entity (context must be 0 for this + call), it is illegal to make any calls on the old parser until + XML_ParserFree has been called on the newly created parser. + If the library has been compiled without support for parameter + entity parsing (ie without XML_DTD being defined), then + XML_SetParamEntityParsing will return 0 if parsing of parameter + entities is requested; otherwise it will return non-zero. + Note: If XML_SetParamEntityParsing is called after XML_Parse or + XML_ParseBuffer, then it has no effect and will always return 0. +*/ +XMLPARSEAPI(int) +XML_SetParamEntityParsing(XML_Parser parser, + enum XML_ParamEntityParsing parsing); + +/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then + XML_GetErrorCode returns information about the error. +*/ +XMLPARSEAPI(enum XML_Error) +XML_GetErrorCode(XML_Parser parser); + +/* These functions return information about the current parse + location. They may be called from any callback called to report + some parse event; in this case the location is the location of the + first of the sequence of characters that generated the event. When + called from callbacks generated by declarations in the document + prologue, the location identified isn't as neatly defined, but will + be within the relevant markup. When called outside of the callback + functions, the position indicated will be just past the last parse + event (regardless of whether there was an associated callback). + + They may also be called after returning from a call to XML_Parse + or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then + the location is the location of the character at which the error + was detected; otherwise the location is the location of the last + parse event, as described above. +*/ +XMLPARSEAPI(int) XML_GetCurrentLineNumber(XML_Parser parser); +XMLPARSEAPI(int) XML_GetCurrentColumnNumber(XML_Parser parser); +XMLPARSEAPI(long) XML_GetCurrentByteIndex(XML_Parser parser); + +/* Return the number of bytes in the current event. + Returns 0 if the event is in an internal entity. +*/ +XMLPARSEAPI(int) +XML_GetCurrentByteCount(XML_Parser parser); + +/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets + the integer pointed to by offset to the offset within this buffer + of the current parse position, and sets the integer pointed to by size + to the size of this buffer (the number of input bytes). Otherwise + returns a NULL pointer. Also returns a NULL pointer if a parse isn't + active. + + NOTE: The character pointer returned should not be used outside + the handler that makes the call. +*/ +XMLPARSEAPI(const char *) +XML_GetInputContext(XML_Parser parser, + int *offset, + int *size); + +/* For backwards compatibility with previous versions. */ +#define XML_GetErrorLineNumber XML_GetCurrentLineNumber +#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber +#define XML_GetErrorByteIndex XML_GetCurrentByteIndex + +/* Frees the content model passed to the element declaration handler */ +XMLPARSEAPI(void) +XML_FreeContentModel(XML_Parser parser, XML_Content *model); + +/* Exposing the memory handling functions used in Expat */ +XMLPARSEAPI(void *) +XML_MemMalloc(XML_Parser parser, size_t size); + +XMLPARSEAPI(void *) +XML_MemRealloc(XML_Parser parser, void *ptr, size_t size); + +XMLPARSEAPI(void) +XML_MemFree(XML_Parser parser, void *ptr); + +/* Frees memory used by the parser. */ +XMLPARSEAPI(void) +XML_ParserFree(XML_Parser parser); + +/* Returns a string describing the error. */ +XMLPARSEAPI(const XML_LChar *) +XML_ErrorString(enum XML_Error code); + +/* Return a string containing the version number of this expat */ +XMLPARSEAPI(const XML_LChar *) +XML_ExpatVersion(void); + +typedef struct { + int major; + int minor; + int micro; +} XML_Expat_Version; + +/* Return an XML_Expat_Version structure containing numeric version + number information for this version of expat. +*/ +XMLPARSEAPI(XML_Expat_Version) +XML_ExpatVersionInfo(void); + +/* Added in Expat 1.95.5. */ +enum XML_FeatureEnum { + XML_FEATURE_END = 0, + XML_FEATURE_UNICODE, + XML_FEATURE_UNICODE_WCHAR_T, + XML_FEATURE_DTD, + XML_FEATURE_CONTEXT_BYTES, + XML_FEATURE_MIN_SIZE, + XML_FEATURE_SIZEOF_XML_CHAR, + XML_FEATURE_SIZEOF_XML_LCHAR + /* Additional features must be added to the end of this enum. */ +}; + +typedef struct { + enum XML_FeatureEnum feature; + const XML_LChar *name; + long int value; +} XML_Feature; + +XMLPARSEAPI(const XML_Feature *) +XML_GetFeatureList(void); + + +/* Expat follows the GNU/Linux convention of odd number minor version for + beta/development releases and even number minor version for stable + releases. Micro is bumped with each release, and set to 0 with each + change to major or minor version. +*/ +#define XML_MAJOR_VERSION 1 +#define XML_MINOR_VERSION 95 +#define XML_MICRO_VERSION 8 + +#ifdef __cplusplus +} +#endif + +#endif /* not XmlParse_INCLUDED */ diff --git a/rosapps/packmgr/lib/functions.cpp b/rosapps/packmgr/lib/functions.cpp index a73d0cec5c7..09050cd2fc8 100644 --- a/rosapps/packmgr/lib/functions.cpp +++ b/rosapps/packmgr/lib/functions.cpp @@ -1,101 +1,101 @@ -//////////////////////////////////////////////////////// -// -// functions.cpp -// -// Script Functions -// -// -// Klemens Friedl, 19.03.2005 -// frik85@hotmail.com -// -//////////////////////////////////////////////////////////////////// - -#include "package.hpp" -#include "script.h" -#include "log.h" - -extern const char* tree_server; -char* PML_Download (pTree, const char* url, const char* server, const char* filename); - - -int debuglog (int argc, char* argv[]) -{ - Log("! SCRIPT DEBUG: "); - LogAdd(argv[1]); - - return ERR_OK; -} - -int download (int argc, char* argv[]) -{ - char* result; - - if (argc==3) - result = PML_Download(NULL, argv[1], argv[3], argv[2]); - - else if (argc==2) - result = PML_Download(NULL, argv[1], NULL, argv[2]); - - else - return ERR_GENERIC; - - if(!result) - return ERR_GENERIC; - - return ERR_OK; - -} - -int extract (int argc, char* argv[]) -{ - return ERR_OK; -} - -int msgbox (int argc, char* argv[]) -{ - if (argc==1) - MessageBoxA(0,argv[1],0,0); - - else if (argc==2) - MessageBoxA(0,argv[1],argv[2],0); - - else - return ERR_GENERIC; - - return ERR_OK; -} - -int shell (int argc, char* argv[]) -{ - // Get the temp dir - char tmp [MAX_PATH]; - GetTempPathA (MAX_PATH, tmp); - - SHELLEXECUTEINFOA info = {0}; - info.cbSize = sizeof(SHELLEXECUTEINFO); - info.fMask = SEE_MASK_NOCLOSEPROCESS; - info.lpVerb = "open"; - info.lpFile = argv[1]; - info.lpDirectory = tmp; - info.nShow = SW_SHOW; - - if(argc >= 2) - info.lpParameters = ""; - - if(!ShellExecuteExA (&info)) - return ERR_GENERIC; - - WaitForSingleObject (info.hProcess, INFINITE); - - return ERR_OK; -} - -const FUNC_TABLE FuncTable[] = -{ - /* Name */ /* Function */ - {"download", download}, - {"extract", extract}, - {"shell", shell}, - {"msgbox", msgbox}, - {"debug", debuglog} -}; +//////////////////////////////////////////////////////// +// +// functions.cpp +// +// Script Functions +// +// +// Klemens Friedl, 19.03.2005 +// frik85@hotmail.com +// +//////////////////////////////////////////////////////////////////// + +#include "package.hpp" +#include "script.h" +#include "log.h" + +extern const char* tree_server; +char* PML_Download (pTree, const char* url, const char* server, const char* filename); + + +int debuglog (int argc, char* argv[]) +{ + Log("! SCRIPT DEBUG: "); + LogAdd(argv[1]); + + return ERR_OK; +} + +int download (int argc, char* argv[]) +{ + char* result; + + if (argc==3) + result = PML_Download(NULL, argv[1], argv[3], argv[2]); + + else if (argc==2) + result = PML_Download(NULL, argv[1], NULL, argv[2]); + + else + return ERR_GENERIC; + + if(!result) + return ERR_GENERIC; + + return ERR_OK; + +} + +int extract (int argc, char* argv[]) +{ + return ERR_OK; +} + +int msgbox (int argc, char* argv[]) +{ + if (argc==1) + MessageBoxA(0,argv[1],0,0); + + else if (argc==2) + MessageBoxA(0,argv[1],argv[2],0); + + else + return ERR_GENERIC; + + return ERR_OK; +} + +int shell (int argc, char* argv[]) +{ + // Get the temp dir + char tmp [MAX_PATH]; + GetTempPathA (MAX_PATH, tmp); + + SHELLEXECUTEINFOA info = {0}; + info.cbSize = sizeof(SHELLEXECUTEINFO); + info.fMask = SEE_MASK_NOCLOSEPROCESS; + info.lpVerb = "open"; + info.lpFile = argv[1]; + info.lpDirectory = tmp; + info.nShow = SW_SHOW; + + if(argc >= 2) + info.lpParameters = ""; + + if(!ShellExecuteExA (&info)) + return ERR_GENERIC; + + WaitForSingleObject (info.hProcess, INFINITE); + + return ERR_OK; +} + +const FUNC_TABLE FuncTable[] = +{ + /* Name */ /* Function */ + {"download", download}, + {"extract", extract}, + {"shell", shell}, + {"msgbox", msgbox}, + {"debug", debuglog} +}; diff --git a/rosapps/packmgr/lib/log.cpp b/rosapps/packmgr/lib/log.cpp index 06f608bff2b..54667b58c6d 100644 --- a/rosapps/packmgr/lib/log.cpp +++ b/rosapps/packmgr/lib/log.cpp @@ -1,117 +1,117 @@ -//////////////////////////////////////////////////////// -// -// log.cpp -// -// Script Functions -// -// -// Klemens Friedl, 19.03.2005 -// frik85@hotmail.com -// -//////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include - -#include "log.h" -#include "package.hpp" // for Package Manager version -#include // ReactOS version: \reactos\include\reactos\version.h - -bool LogCreated = false; - -void Log (const char *message) -{ - FILE *file; - char GTime[80]; - char version[50]; - char versionos[50]; - - if (!LogCreated) - { - file = fopen(LOGFILE, "w"); - LogCreated = true; - - //HTML Header - fputs("Logfile\n", file); - - // date and time - time_t now; - now = time(NULL); - strftime(GTime,sizeof GTime,"%Y-%m-%d",localtime(&now)); - - // package manager version information - wsprintfA(version, " Package Manager %d.%d.%d", - PACKMGR_VERSION_MAJOR, - PACKMGR_VERSION_MINOR, - PACKMGR_VERSION_PATCH_LEVEL); - - // operating system version information - wsprintfA(versionos, " ReactOS %d.%d.%d", - KERNEL_VERSION_MAJOR, - KERNEL_VERSION_MINOR, - KERNEL_VERSION_PATCH_LEVEL); - - // write the head - fputs("

ReactOS Package Manager - Log File

\n", file); - //fputs("WARNING: This is still pre-alpha software.
\n", file); - - fputs("Date: ", file); - fputs(GTime, file); - fputs("
\n", file); - - fputs("Version: ", file); - fputs(version, file); - fputs("
\n", file); - - fputs("OS: ", file); - fputs(versionos, file); - fputs("
\n", file); - } - - else - file = fopen(LOGFILE, "a"); - - if (file == NULL) - { - if (LogCreated) - LogCreated = false; - - return Log(message); - } - - else - { - // Save log entry (+ add time) - fputs("
\n", file); - - time_t now; - now = time(NULL); - strftime(GTime,sizeof GTime,"%I:%M:%S %p",localtime(&now)); - - fputs("", file); - fputs(GTime, file); - fputs(" ", file); - - fputs(message, file); - fclose(file); - } - - if (file) - fclose(file); -} - -void LogAdd (const char *message) -{ - FILE *file; - - file = fopen(LOGFILE, "a"); - - // Save log entry - fputs(message, file); - fclose(file); - - if (file) - fclose(file); -} +//////////////////////////////////////////////////////// +// +// log.cpp +// +// Script Functions +// +// +// Klemens Friedl, 19.03.2005 +// frik85@hotmail.com +// +//////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "log.h" +#include "package.hpp" // for Package Manager version +#include // ReactOS version: \reactos\include\reactos\version.h + +bool LogCreated = false; + +void Log (const char *message) +{ + FILE *file; + char GTime[80]; + char version[50]; + char versionos[50]; + + if (!LogCreated) + { + file = fopen(LOGFILE, "w"); + LogCreated = true; + + //HTML Header + fputs("Logfile\n", file); + + // date and time + time_t now; + now = time(NULL); + strftime(GTime,sizeof GTime,"%Y-%m-%d",localtime(&now)); + + // package manager version information + wsprintfA(version, " Package Manager %d.%d.%d", + PACKMGR_VERSION_MAJOR, + PACKMGR_VERSION_MINOR, + PACKMGR_VERSION_PATCH_LEVEL); + + // operating system version information + wsprintfA(versionos, " ReactOS %d.%d.%d", + KERNEL_VERSION_MAJOR, + KERNEL_VERSION_MINOR, + KERNEL_VERSION_PATCH_LEVEL); + + // write the head + fputs("

ReactOS Package Manager - Log File

\n", file); + //fputs("WARNING: This is still pre-alpha software.
\n", file); + + fputs("Date: ", file); + fputs(GTime, file); + fputs("
\n", file); + + fputs("Version: ", file); + fputs(version, file); + fputs("
\n", file); + + fputs("OS: ", file); + fputs(versionos, file); + fputs("
\n", file); + } + + else + file = fopen(LOGFILE, "a"); + + if (file == NULL) + { + if (LogCreated) + LogCreated = false; + + return Log(message); + } + + else + { + // Save log entry (+ add time) + fputs("
\n", file); + + time_t now; + now = time(NULL); + strftime(GTime,sizeof GTime,"%I:%M:%S %p",localtime(&now)); + + fputs("", file); + fputs(GTime, file); + fputs(" ", file); + + fputs(message, file); + fclose(file); + } + + if (file) + fclose(file); +} + +void LogAdd (const char *message) +{ + FILE *file; + + file = fopen(LOGFILE, "a"); + + // Save log entry + fputs(message, file); + fclose(file); + + if (file) + fclose(file); +} diff --git a/rosapps/packmgr/lib/log.h b/rosapps/packmgr/lib/log.h index a4cda6f87f2..6057cfe9a35 100644 --- a/rosapps/packmgr/lib/log.h +++ b/rosapps/packmgr/lib/log.h @@ -1,21 +1,21 @@ -//////////////////////////////////////////////////////// -// -// log.h -// -// Script Functions -// -// -// Klemens Friedl, 19.03.2005 -// frik85@hotmail.com -// -//////////////////////////////////////////////////////////////////// - -#include -#include - -#define LOGFILE "logfile.html" - -extern bool LogCreated; - -void Log (const char *message); -void LogAdd (const char *message); +//////////////////////////////////////////////////////// +// +// log.h +// +// Script Functions +// +// +// Klemens Friedl, 19.03.2005 +// frik85@hotmail.com +// +//////////////////////////////////////////////////////////////////// + +#include +#include + +#define LOGFILE "logfile.html" + +extern bool LogCreated; + +void Log (const char *message); +void LogAdd (const char *message); diff --git a/rosapps/packmgr/lib/main.cpp b/rosapps/packmgr/lib/main.cpp index f18d292fc0d..db4d1da43dc 100644 --- a/rosapps/packmgr/lib/main.cpp +++ b/rosapps/packmgr/lib/main.cpp @@ -1,192 +1,192 @@ -//////////////////////////////////////////////////////// -// -// main.cpp -// -// Doit stuff and -// everything that fits nowhere else. -// -// -// Maarten Bosma, 09.01.2004 -// maarten.paul@bosma.de -// -//////////////////////////////////////////////////////////////////// - -#include -#include "package.hpp" -#include "log.h" -#include "script.h" - -HANDLE hThread = NULL; -BOOL thread_abort = FALSE; - -char* PML_Download (pTree, const char* url, const char* server = "tree", const char* filename = NULL); - - -// Abort other thread -extern "C" void PML_Abort (void) -{ - thread_abort = TRUE; - - if(hThread) - WaitForSingleObject(hThread, INFINITE); -} - -// Callback function of the "doit"-thread -DWORD WINAPI DoitThread (void* lpParam) -{ - UINT i; - int ret = ERR_OK; - TREE* tree = (TREE*)lpParam; - vector scripts; - - /* Load the scripts */ - - tree->setStatus(0, 0, L"Downloading Install instructions ..."); - - for(i=0; itodo.size(); i++) - { - SCRIPT* script; - - char* path = PML_Download(tree, tree->todo[i]); - - if(RPS_Load(&script, path) == ERR_OK) - scripts.push_back(script); - else - ret = ERR_PACK; - } - - /* Preinstall */ - - Log("* enter preinstall"); - - tree->setStatus(250, 0, L"Preinstall"); - - for(i=0; isetStatus(500, 0, L"Install"); - - for(i=0; isetStatus(750, 0, L"Postinstall"); - - for(i=0; itodo.size(); i++) - RPS_Clear(scripts[i]); - - // clear the todo list - tree->todo.clear(); - - // set all actions to none - for(i=0; ipackages.size(); i++) - PML_SetAction (tree, i, 0, tree->setIcon, NULL); - - tree->setStatus(1000, ret, NULL); - - return 1; -} - -// Do the actions the user wants us to do -extern "C" int PML_DoIt (TREE* tree, PML_SetStatus SetStatus, PML_Ask Ask) -{ - DWORD dummy; - tree->setStatus = SetStatus; - - if(!tree->todo.size()) - return ERR_NOTODO; - - //ask - WCHAR buffer [2000]; - wsprintf(buffer, PML_TransError(ERR_READY), tree->todo.size()); - - if(!Ask(buffer)) - return ERR_GENERIC; - - - hThread = CreateThread(NULL, 0, DoitThread, tree, 0, &dummy); - - if(!hThread) - return ERR_GENERIC; - - LogAdd("\n"); - - return ERR_OK; -} - -// Translates Errorcode into human language -extern "C" WCHAR* PML_TransError (int code) -{ - // I know we, got a memory leak here - static WCHAR string [256]; - - if(!LoadString(GetModuleHandle(L"package"), code, string, 256)) - return PML_TransError(ERR_GENERIC); - - return string; -} - -// Free alloced memory -extern "C" void PML_CloseTree (TREE* tree) -{ - UINT i; - - LogAdd ("\n"); - Log("* free alloced memory"); - Log("* package manager will exit now. Bye!"); - - for(i=0; ipackages.size(); i++) - { - if(tree->packages[i].path) - delete tree->packages[i].path; - - if(tree->packages[i].name) - delete tree->packages[i].name; - - if(tree->packages[i].description) - delete tree->packages[i].description; - - tree->packages.clear(); - - if(tree->packages[i].files[0]) - delete tree->packages[i].files[0]; - - if(tree->packages[i].files[1]) - delete tree->packages[i].files[1]; - - if(tree->packages[i].files[2]) - delete tree->packages[i].files[2]; - - if(tree->packages[i].files[3]) - delete tree->packages[i].files[3]; - } - - tree->descriptionPath.clear(); - tree->todo.clear(); - tree->packages.clear(); - - if(tree) - delete tree; -} - +//////////////////////////////////////////////////////// +// +// main.cpp +// +// Doit stuff and +// everything that fits nowhere else. +// +// +// Maarten Bosma, 09.01.2004 +// maarten.paul@bosma.de +// +//////////////////////////////////////////////////////////////////// + +#include +#include "package.hpp" +#include "log.h" +#include "script.h" + +HANDLE hThread = NULL; +BOOL thread_abort = FALSE; + +char* PML_Download (pTree, const char* url, const char* server = "tree", const char* filename = NULL); + + +// Abort other thread +extern "C" void PML_Abort (void) +{ + thread_abort = TRUE; + + if(hThread) + WaitForSingleObject(hThread, INFINITE); +} + +// Callback function of the "doit"-thread +DWORD WINAPI DoitThread (void* lpParam) +{ + UINT i; + int ret = ERR_OK; + TREE* tree = (TREE*)lpParam; + vector scripts; + + /* Load the scripts */ + + tree->setStatus(0, 0, L"Downloading Install instructions ..."); + + for(i=0; itodo.size(); i++) + { + SCRIPT* script; + + char* path = PML_Download(tree, tree->todo[i]); + + if(RPS_Load(&script, path) == ERR_OK) + scripts.push_back(script); + else + ret = ERR_PACK; + } + + /* Preinstall */ + + Log("* enter preinstall"); + + tree->setStatus(250, 0, L"Preinstall"); + + for(i=0; isetStatus(500, 0, L"Install"); + + for(i=0; isetStatus(750, 0, L"Postinstall"); + + for(i=0; itodo.size(); i++) + RPS_Clear(scripts[i]); + + // clear the todo list + tree->todo.clear(); + + // set all actions to none + for(i=0; ipackages.size(); i++) + PML_SetAction (tree, i, 0, tree->setIcon, NULL); + + tree->setStatus(1000, ret, NULL); + + return 1; +} + +// Do the actions the user wants us to do +extern "C" int PML_DoIt (TREE* tree, PML_SetStatus SetStatus, PML_Ask Ask) +{ + DWORD dummy; + tree->setStatus = SetStatus; + + if(!tree->todo.size()) + return ERR_NOTODO; + + //ask + WCHAR buffer [2000]; + wsprintf(buffer, PML_TransError(ERR_READY), tree->todo.size()); + + if(!Ask(buffer)) + return ERR_GENERIC; + + + hThread = CreateThread(NULL, 0, DoitThread, tree, 0, &dummy); + + if(!hThread) + return ERR_GENERIC; + + LogAdd("\n"); + + return ERR_OK; +} + +// Translates Errorcode into human language +extern "C" WCHAR* PML_TransError (int code) +{ + // I know we, got a memory leak here + static WCHAR string [256]; + + if(!LoadString(GetModuleHandle(L"package"), code, string, 256)) + return PML_TransError(ERR_GENERIC); + + return string; +} + +// Free alloced memory +extern "C" void PML_CloseTree (TREE* tree) +{ + UINT i; + + LogAdd ("\n"); + Log("* free alloced memory"); + Log("* package manager will exit now. Bye!"); + + for(i=0; ipackages.size(); i++) + { + if(tree->packages[i].path) + delete tree->packages[i].path; + + if(tree->packages[i].name) + delete tree->packages[i].name; + + if(tree->packages[i].description) + delete tree->packages[i].description; + + tree->packages.clear(); + + if(tree->packages[i].files[0]) + delete tree->packages[i].files[0]; + + if(tree->packages[i].files[1]) + delete tree->packages[i].files[1]; + + if(tree->packages[i].files[2]) + delete tree->packages[i].files[2]; + + if(tree->packages[i].files[3]) + delete tree->packages[i].files[3]; + } + + tree->descriptionPath.clear(); + tree->todo.clear(); + tree->packages.clear(); + + if(tree) + delete tree; +} + diff --git a/rosapps/packmgr/lib/options.cpp b/rosapps/packmgr/lib/options.cpp index bf41437335c..6c7465320d6 100644 --- a/rosapps/packmgr/lib/options.cpp +++ b/rosapps/packmgr/lib/options.cpp @@ -1,101 +1,101 @@ -//////////////////////////////////////////////////////// -// -// options.cpp -// -// Settting and Loading Options -// -// -// Maarten Bosma, 09.01.2004 -// maarten.paul@bosma.de -// -//////////////////////////////////////////////////////////////////// - -#include "package.hpp" -#include "log.h" -#include "expat.h" - -#include - - -int PML_XmlDownload (pTree tree, const char* url, void* usrdata, - XML_StartElementHandler start, XML_EndElementHandler end, XML_CharacterDataHandler text) ; - - -// expat callback for start of a "node" tag -void opt_start (void* usrdata, const char* tag, const char** arg) -{ - TREE* tree = (TREE*)usrdata; - - if (!strcmp(tag, "source")) - { - tree->sources.push_back((char*)NULL); - tree->field = &tree->sources.back(); - } -} - -// expat callback for end of a "node" tag -void opt_end (void* usrdata, const char* tag) -{ - TREE* tree = (TREE*)usrdata; - - tree->field = NULL; -} - -// expat callback for end of a "node" tag -void opt_text (void* usrdata, const char* data, int len) -{ - TREE* tree = (TREE*)usrdata; - - if(!tree->field) - return; - - *tree->field = new char[len+1]; - strncpy(*tree->field, data, len); - (*tree->field)[len] = '\0'; -} - - - // ! ! ! F I X M E ! ! ! // -/* -int CreateOptions (TREE* tree) -{ - ofstream file ("options.xml"); - - Log("* Creating options.xml from Resources"); - - HRSRC hres = FindResource(GetModuleHandle(L"package"), MAKEINTRESOURCE(123), RT_RCDATA); - if (!hres) - { - Log("! ERROR: Could not load it !"); - return ERR_GENERIC; - } - - MessageBox(0,(WCHAR*)LockResource(LoadResource(NULL, hres)), 0, 0); // is empty - //file << (WCHAR*)LockResource(LoadResource(NULL, hres)); - - return ERR_OK; -} -*/ - -char* PML_Download (pTree, const char* url, const char* server, const char* filename); - -int CreateOptions (TREE* tree) -{ - Log("* Load options.xml from the Internet (Temporary Hack)"); - - CopyFileA( PML_Download(tree, "http://svn.reactos.com/viewcvs/*checkout*/trunk/rosapps/packmgr/lib/options.xml", NULL, "options.xml"), "options.xml", TRUE); - - return ERR_OK; -} - -int LoadOptions (TREE* tree) -{ - int error; - - error = PML_XmlDownload(tree, "file://options.xml", (void*)tree, opt_start, opt_end, opt_text); - if(!error) - return ERR_OK; - - CreateOptions(tree); - return PML_XmlDownload(tree, "file://options.xml", (void*)tree, opt_start, opt_end, opt_text); -} +//////////////////////////////////////////////////////// +// +// options.cpp +// +// Settting and Loading Options +// +// +// Maarten Bosma, 09.01.2004 +// maarten.paul@bosma.de +// +//////////////////////////////////////////////////////////////////// + +#include "package.hpp" +#include "log.h" +#include "expat.h" + +#include + + +int PML_XmlDownload (pTree tree, const char* url, void* usrdata, + XML_StartElementHandler start, XML_EndElementHandler end, XML_CharacterDataHandler text) ; + + +// expat callback for start of a "node" tag +void opt_start (void* usrdata, const char* tag, const char** arg) +{ + TREE* tree = (TREE*)usrdata; + + if (!strcmp(tag, "source")) + { + tree->sources.push_back((char*)NULL); + tree->field = &tree->sources.back(); + } +} + +// expat callback for end of a "node" tag +void opt_end (void* usrdata, const char* tag) +{ + TREE* tree = (TREE*)usrdata; + + tree->field = NULL; +} + +// expat callback for end of a "node" tag +void opt_text (void* usrdata, const char* data, int len) +{ + TREE* tree = (TREE*)usrdata; + + if(!tree->field) + return; + + *tree->field = new char[len+1]; + strncpy(*tree->field, data, len); + (*tree->field)[len] = '\0'; +} + + + // ! ! ! F I X M E ! ! ! // +/* +int CreateOptions (TREE* tree) +{ + ofstream file ("options.xml"); + + Log("* Creating options.xml from Resources"); + + HRSRC hres = FindResource(GetModuleHandle(L"package"), MAKEINTRESOURCE(123), RT_RCDATA); + if (!hres) + { + Log("! ERROR: Could not load it !"); + return ERR_GENERIC; + } + + MessageBox(0,(WCHAR*)LockResource(LoadResource(NULL, hres)), 0, 0); // is empty + //file << (WCHAR*)LockResource(LoadResource(NULL, hres)); + + return ERR_OK; +} +*/ + +char* PML_Download (pTree, const char* url, const char* server, const char* filename); + +int CreateOptions (TREE* tree) +{ + Log("* Load options.xml from the Internet (Temporary Hack)"); + + CopyFileA( PML_Download(tree, "http://svn.reactos.com/viewcvs/*checkout*/trunk/rosapps/packmgr/lib/options.xml", NULL, "options.xml"), "options.xml", TRUE); + + return ERR_OK; +} + +int LoadOptions (TREE* tree) +{ + int error; + + error = PML_XmlDownload(tree, "file://options.xml", (void*)tree, opt_start, opt_end, opt_text); + if(!error) + return ERR_OK; + + CreateOptions(tree); + return PML_XmlDownload(tree, "file://options.xml", (void*)tree, opt_start, opt_end, opt_text); +} diff --git a/rosapps/packmgr/lib/package.cpp b/rosapps/packmgr/lib/package.cpp index c5457565edf..18581450d8d 100644 --- a/rosapps/packmgr/lib/package.cpp +++ b/rosapps/packmgr/lib/package.cpp @@ -1,288 +1,288 @@ -//////////////////////////////////////////////////////// -// -// package.cpp -// -// package related functions -// -// -// Maarten Bosma, 09.01.2004 -// maarten.paul@bosma.de -// -//////////////////////////////////////////////////////////////////// - -#include "package.hpp" -#include "expat.h" -#include "log.h" - -int PML_XmlDownload (pTree, const char* url, void* usrdata, XML_StartElementHandler start, - XML_EndElementHandler end, XML_CharacterDataHandler text=0); - - -// expat callback for start of a package tag -void pack_start (void* usrdata, const char* tag, const char** arg) -{ - int i, id; - PACKAGE* pack = (PACKAGE*)usrdata; - - // if the tag is a script tag ... - if(!strcmp(tag, "scripts")) - { - // ... read the arguments - for (i=0; arg[i]; i+=2) - { - if(!strcmp(arg[i], "inst")) - id = 0; - - else if(!strcmp(arg[i], "update")) - id = 1; - - else if(!strcmp(arg[i], "uinst")) - id = 2; - - else if(!strcmp(arg[i], "srcinst")) - id = 3; - - else - continue; - - pack->files[id] = new char [strlen(arg[i+1])+1]; - strcpy(pack->files[id], arg[i+1]); - } - } - - // ... save the field - else - { - if(!strcmp(tag, "name")) - pack->field = &pack->name; - - else if(!strcmp(tag, "description")) - pack->field = &pack->description; - - else if (!strcmp(tag, "depent")) - { - pack->depencies.push_back((char*)NULL); - pack->field = &pack->depencies.back(); - } - } -} - -// expat callback for end of a package tag -void pack_end (void* usrdata, const char* tag) -{ - PACKAGE* pack = (PACKAGE*)usrdata; - - pack->field = NULL; -} - -// expat callback for text -void pack_text (void* usrdata, const char* data, int len) -{ - PACKAGE* pack = (PACKAGE*)usrdata; - - if(!pack->field) - return; - - *pack->field = new char[len+1]; - strncpy(*pack->field, data, len); - (*pack->field)[len] = '\0'; -} - -// The user clicks on a package -extern "C" int PML_LoadPackage (TREE* tree, int id, PML_SetButton SetButton) -{ - PACKAGE* pack = &tree->packages[id]; - tree->setButton = SetButton; - - if(SetButton) - { - SetButton(1, pack->action); - SetButton(2, pack->inst); // && pack->action != 0 - SetButton(3, pack->src_inst); - SetButton(4, pack->update); - SetButton(5, pack->uninstall); - } - - // root notes (like network) return here - if(!pack->path) - return 1; - - if(!pack->loaded) - { - PML_XmlDownload (tree, pack->path, (void*)pack, pack_start, pack_end, pack_text); - pack->loaded = TRUE; - } - - return ERR_OK; -} - -extern "C" int PML_FindItem (TREE* tree, const char* what) -{ - int i, j; - bool found; - - // if we have children, same action for them - for (i=1; (UINT)ipackages.size(); i++) - { - found = true; - - for(j=0; (UINT)jpackages[i].name[j])) - { - found = false; - break; - } - } - - if(found) - return i; - } - - return 0; -} - -// The user chooses a actions like Install -extern "C" int PML_SetAction (TREE* tree, int id, int action, PML_SetIcon SetIcon, PML_Ask Ask) -{ - UINT i; - int ret = ERR_OK; - - tree->setIcon = SetIcon; - PACKAGE* pack = &tree->packages[id]; - - // if we have children, same action for them - for (i=0; ichildren.size(); i++) - ret = ret || PML_SetAction(tree, pack->children[i], action, SetIcon, Ask); - - // is the action possible ? - if(!pack->actions[action]) - return ERR_GENERIC; - - // is it already set - if(pack->action == action) - return ERR_OK; - - // - if(pack->depencies.size() && action) - { - UINT count = pack->depencies.size(); - WCHAR buffer[2000], buffer2[200]; - wcscpy(buffer, PML_TransError(ERR_DEP1)); - - for (i=0; idepencies.size(); i++) - { - int item = PML_FindItem(tree, pack->depencies[i]); - - if(!item) - return ERR_GENERIC; - - if(action == tree->packages[item].action)// || tree->packages[item].installed - { - count--; - continue; - } - - MultiByteToWideChar (CP_ACP, 0, pack->depencies[i], strlen(pack->depencies[i])+1, buffer2, 200); - wsprintf(buffer, L"%s - %s\n", buffer, buffer2);// - } - - wcscat(buffer, PML_TransError(ERR_DEP2)); - - if(count) - { - if(!Ask(buffer)) - return ERR_GENERIC; - - for (i=0; idepencies.size(); i++) - { - int item = PML_FindItem(tree, pack->depencies[i]); - - tree->packages[item].neededBy.push_back(id); - - PML_SetAction(tree, item, action, SetIcon, Ask); - } - } - } - - // load it if it's not loaded yet - else if (!pack->loaded && pack->path) - { - PML_XmlDownload (tree, pack->path, (void*)pack, pack_start, pack_end, pack_text); - pack->loaded = TRUE; - - return PML_SetAction(tree, id, action, SetIcon, Ask); - } - - // set the icon - if(SetIcon && !pack->icon) - SetIcon(id, action); - - // set the button(s) - if(tree->setButton && action != 2) - { - tree->setButton(1, action); - //tree->setButton(pack->action+1, action); - } - - // can't do src install yet - if(action == 2) - { - MessageBox(0, L"Sorry, but source install is not implemented yet.", 0,0); - return ERR_OK; - } - - // everything but undoing is done here - else if (action != 0) - { - // since we are setting a action we undo it again - if(tree->setButton) - tree->setButton(1, 1); - //tree->setButton(action+1, 0); - - pack->action = action; - - // root notes (like network) return here - if(!pack->path) - return ret; - - // save the name of the corresponding script in a vector - tree->todo.push_back(pack->files[action-1]); - } - - // undoing - else - { - for(i=0; ineededBy.size(); i++) - { - if(tree->packages[pack->neededBy[i]].action) - { - SetIcon(id, pack->action); - return ERR_GENERIC; - } - } - - // root notes (like network) return here - if(!pack->path || pack->action==0) - return ret; - - // erase from todo list - for(i=0; itodo.size(); i++) - if(!strcmp(tree->todo[i], pack->files[pack->action-1])) // look for right entry - tree->todo.erase(tree->todo.begin()+i); // delete it - - // set action back - pack->action = 0; - } - - return ret; -} - -// -extern "C" char* PML_GetDescription (TREE* tree, int id) -{ - PML_LoadPackage(tree, id, NULL); - - return tree->packages[id].description; -} - +//////////////////////////////////////////////////////// +// +// package.cpp +// +// package related functions +// +// +// Maarten Bosma, 09.01.2004 +// maarten.paul@bosma.de +// +//////////////////////////////////////////////////////////////////// + +#include "package.hpp" +#include "expat.h" +#include "log.h" + +int PML_XmlDownload (pTree, const char* url, void* usrdata, XML_StartElementHandler start, + XML_EndElementHandler end, XML_CharacterDataHandler text=0); + + +// expat callback for start of a package tag +void pack_start (void* usrdata, const char* tag, const char** arg) +{ + int i, id; + PACKAGE* pack = (PACKAGE*)usrdata; + + // if the tag is a script tag ... + if(!strcmp(tag, "scripts")) + { + // ... read the arguments + for (i=0; arg[i]; i+=2) + { + if(!strcmp(arg[i], "inst")) + id = 0; + + else if(!strcmp(arg[i], "update")) + id = 1; + + else if(!strcmp(arg[i], "uinst")) + id = 2; + + else if(!strcmp(arg[i], "srcinst")) + id = 3; + + else + continue; + + pack->files[id] = new char [strlen(arg[i+1])+1]; + strcpy(pack->files[id], arg[i+1]); + } + } + + // ... save the field + else + { + if(!strcmp(tag, "name")) + pack->field = &pack->name; + + else if(!strcmp(tag, "description")) + pack->field = &pack->description; + + else if (!strcmp(tag, "depent")) + { + pack->depencies.push_back((char*)NULL); + pack->field = &pack->depencies.back(); + } + } +} + +// expat callback for end of a package tag +void pack_end (void* usrdata, const char* tag) +{ + PACKAGE* pack = (PACKAGE*)usrdata; + + pack->field = NULL; +} + +// expat callback for text +void pack_text (void* usrdata, const char* data, int len) +{ + PACKAGE* pack = (PACKAGE*)usrdata; + + if(!pack->field) + return; + + *pack->field = new char[len+1]; + strncpy(*pack->field, data, len); + (*pack->field)[len] = '\0'; +} + +// The user clicks on a package +extern "C" int PML_LoadPackage (TREE* tree, int id, PML_SetButton SetButton) +{ + PACKAGE* pack = &tree->packages[id]; + tree->setButton = SetButton; + + if(SetButton) + { + SetButton(1, pack->action); + SetButton(2, pack->inst); // && pack->action != 0 + SetButton(3, pack->src_inst); + SetButton(4, pack->update); + SetButton(5, pack->uninstall); + } + + // root notes (like network) return here + if(!pack->path) + return 1; + + if(!pack->loaded) + { + PML_XmlDownload (tree, pack->path, (void*)pack, pack_start, pack_end, pack_text); + pack->loaded = TRUE; + } + + return ERR_OK; +} + +extern "C" int PML_FindItem (TREE* tree, const char* what) +{ + int i, j; + bool found; + + // if we have children, same action for them + for (i=1; (UINT)ipackages.size(); i++) + { + found = true; + + for(j=0; (UINT)jpackages[i].name[j])) + { + found = false; + break; + } + } + + if(found) + return i; + } + + return 0; +} + +// The user chooses a actions like Install +extern "C" int PML_SetAction (TREE* tree, int id, int action, PML_SetIcon SetIcon, PML_Ask Ask) +{ + UINT i; + int ret = ERR_OK; + + tree->setIcon = SetIcon; + PACKAGE* pack = &tree->packages[id]; + + // if we have children, same action for them + for (i=0; ichildren.size(); i++) + ret = ret || PML_SetAction(tree, pack->children[i], action, SetIcon, Ask); + + // is the action possible ? + if(!pack->actions[action]) + return ERR_GENERIC; + + // is it already set + if(pack->action == action) + return ERR_OK; + + // + if(pack->depencies.size() && action) + { + UINT count = pack->depencies.size(); + WCHAR buffer[2000], buffer2[200]; + wcscpy(buffer, PML_TransError(ERR_DEP1)); + + for (i=0; idepencies.size(); i++) + { + int item = PML_FindItem(tree, pack->depencies[i]); + + if(!item) + return ERR_GENERIC; + + if(action == tree->packages[item].action)// || tree->packages[item].installed + { + count--; + continue; + } + + MultiByteToWideChar (CP_ACP, 0, pack->depencies[i], strlen(pack->depencies[i])+1, buffer2, 200); + wsprintf(buffer, L"%s - %s\n", buffer, buffer2);// + } + + wcscat(buffer, PML_TransError(ERR_DEP2)); + + if(count) + { + if(!Ask(buffer)) + return ERR_GENERIC; + + for (i=0; idepencies.size(); i++) + { + int item = PML_FindItem(tree, pack->depencies[i]); + + tree->packages[item].neededBy.push_back(id); + + PML_SetAction(tree, item, action, SetIcon, Ask); + } + } + } + + // load it if it's not loaded yet + else if (!pack->loaded && pack->path) + { + PML_XmlDownload (tree, pack->path, (void*)pack, pack_start, pack_end, pack_text); + pack->loaded = TRUE; + + return PML_SetAction(tree, id, action, SetIcon, Ask); + } + + // set the icon + if(SetIcon && !pack->icon) + SetIcon(id, action); + + // set the button(s) + if(tree->setButton && action != 2) + { + tree->setButton(1, action); + //tree->setButton(pack->action+1, action); + } + + // can't do src install yet + if(action == 2) + { + MessageBox(0, L"Sorry, but source install is not implemented yet.", 0,0); + return ERR_OK; + } + + // everything but undoing is done here + else if (action != 0) + { + // since we are setting a action we undo it again + if(tree->setButton) + tree->setButton(1, 1); + //tree->setButton(action+1, 0); + + pack->action = action; + + // root notes (like network) return here + if(!pack->path) + return ret; + + // save the name of the corresponding script in a vector + tree->todo.push_back(pack->files[action-1]); + } + + // undoing + else + { + for(i=0; ineededBy.size(); i++) + { + if(tree->packages[pack->neededBy[i]].action) + { + SetIcon(id, pack->action); + return ERR_GENERIC; + } + } + + // root notes (like network) return here + if(!pack->path || pack->action==0) + return ret; + + // erase from todo list + for(i=0; itodo.size(); i++) + if(!strcmp(tree->todo[i], pack->files[pack->action-1])) // look for right entry + tree->todo.erase(tree->todo.begin()+i); // delete it + + // set action back + pack->action = 0; + } + + return ret; +} + +// +extern "C" char* PML_GetDescription (TREE* tree, int id) +{ + PML_LoadPackage(tree, id, NULL); + + return tree->packages[id].description; +} + diff --git a/rosapps/packmgr/lib/package.h b/rosapps/packmgr/lib/package.h index 68b8bd46b3b..e33c63c758c 100644 --- a/rosapps/packmgr/lib/package.h +++ b/rosapps/packmgr/lib/package.h @@ -1,47 +1,47 @@ -//////////////////////////////////////////////// -// -// package.hpp -// Package C++ Header -//////////////////////////////////////////////// - -#include -#include "error.h" - - -/* Callbacks */ - -typedef int (*PML_AddItem) (int id, const char* name, int parent, int icon); -typedef int (*PML_SetStatus) (int status1, int status2, WCHAR* text); -typedef int (*PML_SetButton) (DWORD dwID, BOOL state); -typedef int (*PML_SetIcon) (int id, int icon); -typedef int (*PML_SetText) (const char* text); -typedef int (*PML_Ask) (const WCHAR* text); - - -/* Structs */ - -typedef void* pTree; - -#define MAXNODES 10000 - - -/* Prototypes */ - -void PML_Abort (void); -WCHAR* PML_TransError (int code); - -int PML_LoadTree (pTree*, char* url, PML_AddItem); -int PML_FindItem (pTree tree, const char* what); -int PML_LoadPackage (pTree, int id, PML_SetButton); -char* PML_GetDescription (pTree tree, int id); -int PML_SetAction (pTree, int package, int action, PML_SetIcon, PML_Ask); -int PML_DoIt (pTree, PML_SetStatus, PML_Ask); - -void PML_CloseTree (pTree); - - -/* Version */ - -#define PACKMGR_VERSION_MAJOR 0 -#define PACKMGR_VERSION_MINOR 3 -#define PACKMGR_VERSION_PATCH_LEVEL 1 +//////////////////////////////////////////////// +// +// package.hpp +// Package C++ Header +//////////////////////////////////////////////// + +#include +#include "error.h" + + +/* Callbacks */ + +typedef int (*PML_AddItem) (int id, const char* name, int parent, int icon); +typedef int (*PML_SetStatus) (int status1, int status2, WCHAR* text); +typedef int (*PML_SetButton) (DWORD dwID, BOOL state); +typedef int (*PML_SetIcon) (int id, int icon); +typedef int (*PML_SetText) (const char* text); +typedef int (*PML_Ask) (const WCHAR* text); + + +/* Structs */ + +typedef void* pTree; + +#define MAXNODES 10000 + + +/* Prototypes */ + +void PML_Abort (void); +WCHAR* PML_TransError (int code); + +int PML_LoadTree (pTree*, char* url, PML_AddItem); +int PML_FindItem (pTree tree, const char* what); +int PML_LoadPackage (pTree, int id, PML_SetButton); +char* PML_GetDescription (pTree tree, int id); +int PML_SetAction (pTree, int package, int action, PML_SetIcon, PML_Ask); +int PML_DoIt (pTree, PML_SetStatus, PML_Ask); + +void PML_CloseTree (pTree); + + +/* Version */ + +#define PACKMGR_VERSION_MAJOR 0 +#define PACKMGR_VERSION_MINOR 3 +#define PACKMGR_VERSION_PATCH_LEVEL 1 diff --git a/rosapps/packmgr/lib/package.hpp b/rosapps/packmgr/lib/package.hpp index 0447317b482..d29ae5a8679 100644 --- a/rosapps/packmgr/lib/package.hpp +++ b/rosapps/packmgr/lib/package.hpp @@ -1,92 +1,92 @@ -//////////////////////////////////////////////// -// -// package.hpp -// Package C++ Header -//////////////////////////////////////////////// - -#include -#include -#include "error.h" - -using namespace std; - - -/* Callbacks */ - -typedef int (*PML_AddItem) (int id, const char* name, int parent, int icon); -typedef int (*PML_SetStatus) (int status1, int status2, WCHAR* text); -typedef int (*PML_SetButton) (DWORD dwID, BOOL state); -typedef int (*PML_SetIcon) (int id, int icon); -typedef int (*PML_SetText) (const char* text); -typedef int (*PML_Ask) (const WCHAR* text); - - -/* Structs */ - -typedef struct -{ - char* path; - char* name; - char* description; - char** field; - - BOOL icon; - BOOL loaded; - vector neededBy; - vector children; - vector depencies; - - int action; - char* files [4]; - - union //which actions are possible - { - struct { BOOL none, inst, src_inst, update, uninstall; }; - BOOL actions [4]; - }; - -} PACKAGE; - -typedef struct -{ - char** field; - - vector todo; - vector sources; - vector descriptionPath; - vector packages; - - PML_AddItem addItem; - PML_SetButton setButton; - PML_SetStatus setStatus; - PML_SetIcon setIcon; - PML_SetText setText; - -} TREE, *pTree; - -#define MAXNODES 10000 - - -/* Prototypes */ - -extern "C" -{ - void PML_Abort (void); - WCHAR* PML_TransError (int code); - - int PML_LoadTree (pTree*, char* url, PML_AddItem); - int PML_FindItem (TREE* tree, const char* what); - int PML_LoadPackage (pTree, int id, PML_SetButton); - char* PML_GetDescription (TREE* tree, int id); - int PML_SetAction (pTree, int package, int action, PML_SetIcon, PML_Ask); - int PML_DoIt (pTree, PML_SetStatus, PML_Ask); - - void PML_CloseTree (pTree); -} - - -/* Version */ - -#define PACKMGR_VERSION_MAJOR 0 -#define PACKMGR_VERSION_MINOR 3 -#define PACKMGR_VERSION_PATCH_LEVEL 1 +//////////////////////////////////////////////// +// +// package.hpp +// Package C++ Header +//////////////////////////////////////////////// + +#include +#include +#include "error.h" + +using namespace std; + + +/* Callbacks */ + +typedef int (*PML_AddItem) (int id, const char* name, int parent, int icon); +typedef int (*PML_SetStatus) (int status1, int status2, WCHAR* text); +typedef int (*PML_SetButton) (DWORD dwID, BOOL state); +typedef int (*PML_SetIcon) (int id, int icon); +typedef int (*PML_SetText) (const char* text); +typedef int (*PML_Ask) (const WCHAR* text); + + +/* Structs */ + +typedef struct +{ + char* path; + char* name; + char* description; + char** field; + + BOOL icon; + BOOL loaded; + vector neededBy; + vector children; + vector depencies; + + int action; + char* files [4]; + + union //which actions are possible + { + struct { BOOL none, inst, src_inst, update, uninstall; }; + BOOL actions [4]; + }; + +} PACKAGE; + +typedef struct +{ + char** field; + + vector todo; + vector sources; + vector descriptionPath; + vector packages; + + PML_AddItem addItem; + PML_SetButton setButton; + PML_SetStatus setStatus; + PML_SetIcon setIcon; + PML_SetText setText; + +} TREE, *pTree; + +#define MAXNODES 10000 + + +/* Prototypes */ + +extern "C" +{ + void PML_Abort (void); + WCHAR* PML_TransError (int code); + + int PML_LoadTree (pTree*, char* url, PML_AddItem); + int PML_FindItem (TREE* tree, const char* what); + int PML_LoadPackage (pTree, int id, PML_SetButton); + char* PML_GetDescription (TREE* tree, int id); + int PML_SetAction (pTree, int package, int action, PML_SetIcon, PML_Ask); + int PML_DoIt (pTree, PML_SetStatus, PML_Ask); + + void PML_CloseTree (pTree); +} + + +/* Version */ + +#define PACKMGR_VERSION_MAJOR 0 +#define PACKMGR_VERSION_MINOR 3 +#define PACKMGR_VERSION_PATCH_LEVEL 1 diff --git a/rosapps/packmgr/lib/script.cpp b/rosapps/packmgr/lib/script.cpp index 6c52ef8116a..782a4454fae 100644 --- a/rosapps/packmgr/lib/script.cpp +++ b/rosapps/packmgr/lib/script.cpp @@ -1,278 +1,278 @@ -//////////////////////////////////////////////////////// -// -// script.cpp -// -// Implementaion of a basic basic :) interpreter -// -// -// Maarten Bosma, 09.01.2004 -// maarten.paul@bosma.de -// -//////////////////////////////////////////////////////////////////// - -#include "package.hpp" -#include "script.h" -#include "log.h" -#include - -using namespace std; - -// just a few Helpers -void Replace (string* Where, string Old, string New, int start = 0, int end = -1, int instring = 1); -int FindCount (string What, string Where, int start = 0, int end = -1); -int Find (string Where, string What, int start = 0, int end = -1, int instring = 1); - - -// Loads script from file, checks if it's synaxially correct -// and converts it into a easy to interprete one. -int RPS_Load (SCRIPT** script, const char* path) -{ - string source; - - /* We have to do it that way (doublepointer) because MinGw - calls "delete" at the end of function otherwise. */ - (*script) = new SCRIPT; - - // Load file to string - ifstream file(path, ios_base::in); - if (!file.is_open()) - return ERR_FILE; - - getline(file, source, '\0'); - - // make sure last char is a new line - source += "\n"; - - // Are all subs and strings closed ? - // FIXME: Just a quick hack sould be both checked line by line - if(FindCount(source, "\"")%2) // if count is uneven not all strings are closed - return ERR_SYNATX; - - if(FindCount(source, "Sub ") != FindCount(source, "End Sub\n")) - return ERR_SYNATX; - - // Delete comments - while (true) - { - int start = Find(source, "'"); - if(start == NOTFOUND) - break; - int end = Find(source, "\n", start); - source.erase(start, end-start); // needs size not line - } - - // Converte the file into some thing easier to interprete - Replace(&source, "(", " "); - Replace(&source, ")", " "); - Replace(&source, ";", " "); - Replace(&source, ",", " "); - Replace(&source, "\"", " \" "); - Replace(&source, "\t", " "); - - Replace(&source, " ", " "); - Replace(&source, "\n ", "\n"); - Replace(&source, " \n", "\n"); - Replace(&source, "\n\n", "\n"); - - if(source[0]=='\n') - source.erase(0,1); - - // copy string into struct (line by line) - UINT i, line=0; - for (i=0; i < source.size(); i++) - { - // Make everything non capital letters - if (source[i] >= 65 && source[i] <= 90) // ASCII-Code (A-Z 65-90) - { - source[i] += 32; // ASCII-Code (a-z 97-122) - } - - else if (source[i] == '\"') - { - while(source[++i]!='\"'); - } - - else if (source[i] == '\n') - { - (*script)->code.push_back(source.substr(line, i-line)); - line = i+1; - } - } - - // create a sub table (with name, beginnig and end of function) - for (i=0; i < (*script)->code.size(); i++) // code.size() is the cout of lines - { - SUB sub; - - if((*script)->code[i].substr(0,4) != "sub ") - return ERR_SYNATX; // script has to start with sub - - sub.name = (*script)->code[i].substr(4,((*script)->code[i].size()-4)); - sub.start = i+1; - - while ((*script)->code[i] != "end sub") - { - i++; - //if script does not end with "end sub" we got a problem - if (i>(*script)->code.size()) - return ERR_SYNATX; - } - - sub.end = i; - (*script)->subs.push_back(sub); - } - - return ERR_OK; -} - - -// Executes a subroutine of the script -int RPS_Execute (SCRIPT* script, const char* function) -{ - char *argv[100]; - char *buffer; - int a, b, c, nr = NOTFOUND, argc = 0; - - // find the right fuction - for(a=0; (UINT)asubs.size(); a++) - if(script->subs[a].name == function) - nr = a; - - // if there isn't a fuction with this name we can't do anything - if(nr == NOTFOUND) - return ERR_OK; - - // call the function - for (a=script->subs[nr].start; asubs[nr].end; a++) - { - // create a temporarry buffer - buffer = new char[script->code[a].size()]; - strcpy(buffer, script->code[a].c_str()); - - // make the fist argument the function's name - argv[0] = &buffer[0]; - - int buffer_size = (int)strlen(buffer); - for (b=0; bend)) - break; - start = pos+1; - counter++; - } - - return counter; -} - -// Find (with only or not in Strings option) -int Find (string where, string what, int start, int end, int instring) -{ - int pos = (int)where.find (what, start); - - //could could not be found or is outside of search area - if (pos == (int)string::npos || (end!=-1 && pos>end)) - return -1; - - // if the count of this quotes is eaven we are in string - int isInString = FindCount(where, "\"", start, pos)%2; - - // if so we go on searching - if(isInString == instring) - return Find (where, what, pos+1, end, instring); - - return pos; - -} - -// Replace (using Find) -void Replace (string* String, string Old, string New, int start, int end, int instring) -{ - int pos = start; - - while(true) - { - pos = Find(String->c_str(), Old, pos, end, instring); - if (pos == -1) - break; - - String->replace (pos, Old.length(), New); - } -} +//////////////////////////////////////////////////////// +// +// script.cpp +// +// Implementaion of a basic basic :) interpreter +// +// +// Maarten Bosma, 09.01.2004 +// maarten.paul@bosma.de +// +//////////////////////////////////////////////////////////////////// + +#include "package.hpp" +#include "script.h" +#include "log.h" +#include + +using namespace std; + +// just a few Helpers +void Replace (string* Where, string Old, string New, int start = 0, int end = -1, int instring = 1); +int FindCount (string What, string Where, int start = 0, int end = -1); +int Find (string Where, string What, int start = 0, int end = -1, int instring = 1); + + +// Loads script from file, checks if it's synaxially correct +// and converts it into a easy to interprete one. +int RPS_Load (SCRIPT** script, const char* path) +{ + string source; + + /* We have to do it that way (doublepointer) because MinGw + calls "delete" at the end of function otherwise. */ + (*script) = new SCRIPT; + + // Load file to string + ifstream file(path, ios_base::in); + if (!file.is_open()) + return ERR_FILE; + + getline(file, source, '\0'); + + // make sure last char is a new line + source += "\n"; + + // Are all subs and strings closed ? + // FIXME: Just a quick hack sould be both checked line by line + if(FindCount(source, "\"")%2) // if count is uneven not all strings are closed + return ERR_SYNATX; + + if(FindCount(source, "Sub ") != FindCount(source, "End Sub\n")) + return ERR_SYNATX; + + // Delete comments + while (true) + { + int start = Find(source, "'"); + if(start == NOTFOUND) + break; + int end = Find(source, "\n", start); + source.erase(start, end-start); // needs size not line + } + + // Converte the file into some thing easier to interprete + Replace(&source, "(", " "); + Replace(&source, ")", " "); + Replace(&source, ";", " "); + Replace(&source, ",", " "); + Replace(&source, "\"", " \" "); + Replace(&source, "\t", " "); + + Replace(&source, " ", " "); + Replace(&source, "\n ", "\n"); + Replace(&source, " \n", "\n"); + Replace(&source, "\n\n", "\n"); + + if(source[0]=='\n') + source.erase(0,1); + + // copy string into struct (line by line) + UINT i, line=0; + for (i=0; i < source.size(); i++) + { + // Make everything non capital letters + if (source[i] >= 65 && source[i] <= 90) // ASCII-Code (A-Z 65-90) + { + source[i] += 32; // ASCII-Code (a-z 97-122) + } + + else if (source[i] == '\"') + { + while(source[++i]!='\"'); + } + + else if (source[i] == '\n') + { + (*script)->code.push_back(source.substr(line, i-line)); + line = i+1; + } + } + + // create a sub table (with name, beginnig and end of function) + for (i=0; i < (*script)->code.size(); i++) // code.size() is the cout of lines + { + SUB sub; + + if((*script)->code[i].substr(0,4) != "sub ") + return ERR_SYNATX; // script has to start with sub + + sub.name = (*script)->code[i].substr(4,((*script)->code[i].size()-4)); + sub.start = i+1; + + while ((*script)->code[i] != "end sub") + { + i++; + //if script does not end with "end sub" we got a problem + if (i>(*script)->code.size()) + return ERR_SYNATX; + } + + sub.end = i; + (*script)->subs.push_back(sub); + } + + return ERR_OK; +} + + +// Executes a subroutine of the script +int RPS_Execute (SCRIPT* script, const char* function) +{ + char *argv[100]; + char *buffer; + int a, b, c, nr = NOTFOUND, argc = 0; + + // find the right fuction + for(a=0; (UINT)asubs.size(); a++) + if(script->subs[a].name == function) + nr = a; + + // if there isn't a fuction with this name we can't do anything + if(nr == NOTFOUND) + return ERR_OK; + + // call the function + for (a=script->subs[nr].start; asubs[nr].end; a++) + { + // create a temporarry buffer + buffer = new char[script->code[a].size()]; + strcpy(buffer, script->code[a].c_str()); + + // make the fist argument the function's name + argv[0] = &buffer[0]; + + int buffer_size = (int)strlen(buffer); + for (b=0; bend)) + break; + start = pos+1; + counter++; + } + + return counter; +} + +// Find (with only or not in Strings option) +int Find (string where, string what, int start, int end, int instring) +{ + int pos = (int)where.find (what, start); + + //could could not be found or is outside of search area + if (pos == (int)string::npos || (end!=-1 && pos>end)) + return -1; + + // if the count of this quotes is eaven we are in string + int isInString = FindCount(where, "\"", start, pos)%2; + + // if so we go on searching + if(isInString == instring) + return Find (where, what, pos+1, end, instring); + + return pos; + +} + +// Replace (using Find) +void Replace (string* String, string Old, string New, int start, int end, int instring) +{ + int pos = start; + + while(true) + { + pos = Find(String->c_str(), Old, pos, end, instring); + if (pos == -1) + break; + + String->replace (pos, Old.length(), New); + } +} diff --git a/rosapps/packmgr/lib/script.h b/rosapps/packmgr/lib/script.h index 76778742793..b0260f2089f 100644 --- a/rosapps/packmgr/lib/script.h +++ b/rosapps/packmgr/lib/script.h @@ -1,65 +1,65 @@ -//////////////////////////////////////////////// -// -// package.hpp -// Header for the script stuff -//////////////////////////////////////////////// - -#include -#include - -using namespace std; - - -/* Structs */ - -typedef struct -{ - string name; - int start, end; - -} SUB; - -typedef struct -{ - vector code; - vector subs; - -} SCRIPT; - - -/* Prototypes */ - -int RPS_Load (SCRIPT** script, const char* path); -int RPS_Execute (SCRIPT* script, const char* function); -int RPS_getVar (const char* name); -void RPS_Clear (SCRIPT* script); - - -/* Callbacks */ - -typedef int (*FUNC_PROC)(int, char**); // function callback - - -/* Function table */ - -typedef struct -{ - char* name; - FUNC_PROC function; -} FUNC_TABLE; - -// very function is listed in there -extern const FUNC_TABLE FuncTable[]; - -// count of functions -#define FUNC_COUNT 3 - - -/* For the helper-funtions */ - -#define STR_NO 0x1; -#define STR_ONLY 0x0; -#define STR_YES 0x2; - -// ^^ I would write down here that they -// mean but I don't know anymore myself :O +//////////////////////////////////////////////// +// +// package.hpp +// Header for the script stuff +//////////////////////////////////////////////// + +#include +#include + +using namespace std; + + +/* Structs */ + +typedef struct +{ + string name; + int start, end; + +} SUB; + +typedef struct +{ + vector code; + vector subs; + +} SCRIPT; + + +/* Prototypes */ + +int RPS_Load (SCRIPT** script, const char* path); +int RPS_Execute (SCRIPT* script, const char* function); +int RPS_getVar (const char* name); +void RPS_Clear (SCRIPT* script); + + +/* Callbacks */ + +typedef int (*FUNC_PROC)(int, char**); // function callback + + +/* Function table */ + +typedef struct +{ + char* name; + FUNC_PROC function; +} FUNC_TABLE; + +// very function is listed in there +extern const FUNC_TABLE FuncTable[]; + +// count of functions +#define FUNC_COUNT 3 + + +/* For the helper-funtions */ + +#define STR_NO 0x1; +#define STR_ONLY 0x0; +#define STR_YES 0x2; + +// ^^ I would write down here that they +// mean but I don't know anymore myself :O diff --git a/rosapps/packmgr/lib/tree.cpp b/rosapps/packmgr/lib/tree.cpp index 867a74b367a..cca821ce97a 100644 --- a/rosapps/packmgr/lib/tree.cpp +++ b/rosapps/packmgr/lib/tree.cpp @@ -1,126 +1,126 @@ -//////////////////////////////////////////////////////// -// -// tree.cpp -// -// Loading of the package tree -// -// -// Maarten Bosma, 09.01.2004 -// maarten.paul@bosma.de -// -//////////////////////////////////////////////////////////////////// - -#include "package.hpp" -#include "expat.h" - -vector parents; - -int LoadOptions (TREE* tree); - -void tree_end (void* tree, const char* tag); -void tree_start (void* usrdata, const char* tag, const char** arg); - -int PML_XmlDownload (pTree tree, const char* file, void* usrdata, XML_StartElementHandler start, - XML_EndElementHandler end, XML_CharacterDataHandler text=0); - - -// Load the tree -extern "C" int PML_LoadTree (TREE** tree, char* url, PML_AddItem AddItem) -{ - // get the memory - (*tree) = new TREE; - - // set every to zero - memset((*tree), 0, sizeof((*tree))); - - // set addItem callback - (*tree)->addItem = AddItem; - - LoadOptions(*tree); - - return PML_XmlDownload (*tree, url, (void*)(*tree), tree_start, tree_end); -} - -// expat callback for start of a "node" tag -void tree_start (void* usrdata, const char* tag, const char** arg) -{ - int i, icon = 0; - static int id = 1; - - TREE* tree = (TREE*)usrdata; - - // ignore if tag is the root tag ("tree") - if(!strcmp(tag, "tree")) - return; - - // set the package memory - tree->packages.resize(id+1); - memset(&tree->packages[id], 0, sizeof(tree->packages[id])); - - tree->packages[id].loaded = FALSE; - tree->packages[id].icon = FALSE; - tree->packages[id].none = TRUE; - tree->packages[id].path = NULL; - tree->packages[id].name = "\0"; - - // read the arguments - for (i=0; arg[i]; i+=2) - { - if(!strcmp(arg[i], "name")) - { - tree->packages[id].name = new char [strlen(arg[i+1])+1]; - strcpy(tree->packages[id].name, arg[i+1]); - } - - if(!strcmp(arg[i], "icon")) - { - icon = atoi(arg[i+1]); - tree->packages[id].icon = TRUE; - } - - if(!strcmp(arg[i], "file")) - { - tree->packages[id].path = new char [strlen(arg[i+1])+1]; - strcpy(tree->packages[id].path, arg[i+1]); - - if(strcmp(tag, "bin")) - tree->packages[id].inst = TRUE; - - if(strcmp(tag, "src")) - tree->packages[id].src_inst = TRUE; - } - } - - if(tree->packages[id].name[0] == '\0') return; - - // add it - if(!parents.size()) - { - if(tree->addItem) - tree->addItem(id, tree->packages[id].name, 0, icon); - } - - // do some manipulation at the parent - else - { - if(tree->addItem) - tree->addItem(id, tree->packages[id].name, parents.back(), icon); - - // list as child in the parent node - tree->packages[parents.back()].children.push_back(id); - - // this is for the buttons - tree->packages[parents.back()].inst = tree->packages[parents.back()].inst || tree->packages[id].inst; - tree->packages[parents.back()].src_inst = tree->packages[parents.back()].src_inst || tree->packages[id].src_inst; - } - - parents.push_back(id++); -} - -// expat callback for end of a "node" tag -void tree_end (void* tree, const char* tag) -{ - // delete last item - parents.pop_back(); -} - +//////////////////////////////////////////////////////// +// +// tree.cpp +// +// Loading of the package tree +// +// +// Maarten Bosma, 09.01.2004 +// maarten.paul@bosma.de +// +//////////////////////////////////////////////////////////////////// + +#include "package.hpp" +#include "expat.h" + +vector parents; + +int LoadOptions (TREE* tree); + +void tree_end (void* tree, const char* tag); +void tree_start (void* usrdata, const char* tag, const char** arg); + +int PML_XmlDownload (pTree tree, const char* file, void* usrdata, XML_StartElementHandler start, + XML_EndElementHandler end, XML_CharacterDataHandler text=0); + + +// Load the tree +extern "C" int PML_LoadTree (TREE** tree, char* url, PML_AddItem AddItem) +{ + // get the memory + (*tree) = new TREE; + + // set every to zero + memset((*tree), 0, sizeof((*tree))); + + // set addItem callback + (*tree)->addItem = AddItem; + + LoadOptions(*tree); + + return PML_XmlDownload (*tree, url, (void*)(*tree), tree_start, tree_end); +} + +// expat callback for start of a "node" tag +void tree_start (void* usrdata, const char* tag, const char** arg) +{ + int i, icon = 0; + static int id = 1; + + TREE* tree = (TREE*)usrdata; + + // ignore if tag is the root tag ("tree") + if(!strcmp(tag, "tree")) + return; + + // set the package memory + tree->packages.resize(id+1); + memset(&tree->packages[id], 0, sizeof(tree->packages[id])); + + tree->packages[id].loaded = FALSE; + tree->packages[id].icon = FALSE; + tree->packages[id].none = TRUE; + tree->packages[id].path = NULL; + tree->packages[id].name = "\0"; + + // read the arguments + for (i=0; arg[i]; i+=2) + { + if(!strcmp(arg[i], "name")) + { + tree->packages[id].name = new char [strlen(arg[i+1])+1]; + strcpy(tree->packages[id].name, arg[i+1]); + } + + if(!strcmp(arg[i], "icon")) + { + icon = atoi(arg[i+1]); + tree->packages[id].icon = TRUE; + } + + if(!strcmp(arg[i], "file")) + { + tree->packages[id].path = new char [strlen(arg[i+1])+1]; + strcpy(tree->packages[id].path, arg[i+1]); + + if(strcmp(tag, "bin")) + tree->packages[id].inst = TRUE; + + if(strcmp(tag, "src")) + tree->packages[id].src_inst = TRUE; + } + } + + if(tree->packages[id].name[0] == '\0') return; + + // add it + if(!parents.size()) + { + if(tree->addItem) + tree->addItem(id, tree->packages[id].name, 0, icon); + } + + // do some manipulation at the parent + else + { + if(tree->addItem) + tree->addItem(id, tree->packages[id].name, parents.back(), icon); + + // list as child in the parent node + tree->packages[parents.back()].children.push_back(id); + + // this is for the buttons + tree->packages[parents.back()].inst = tree->packages[parents.back()].inst || tree->packages[id].inst; + tree->packages[parents.back()].src_inst = tree->packages[parents.back()].src_inst || tree->packages[id].src_inst; + } + + parents.push_back(id++); +} + +// expat callback for end of a "node" tag +void tree_end (void* tree, const char* tag) +{ + // delete last item + parents.pop_back(); +} + diff --git a/rosapps/sysutils/ctm/resource.h b/rosapps/sysutils/ctm/resource.h index fc01f17b225..8a8406b193c 100644 --- a/rosapps/sysutils/ctm/resource.h +++ b/rosapps/sysutils/ctm/resource.h @@ -1,44 +1,44 @@ -/* - * CTM resource definitions - * - * Copyright 2004 ReactOS team - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define IDS_APP_TITLE 0 - -#define IDS_COLUMN_IMAGENAME 10 -#define IDS_COLUMN_PID 11 -#define IDS_COLUMN_CPU 12 -#define IDS_COLUMN_MEM 13 -#define IDS_COLUMN_MEM_UNIT 14 -#define IDS_COLUMN_PF 15 - -#define IDS_IDLE_PROCESS 100 -#define IDS_YES 101 -#define IDS_NO 102 - -#define IDS_MENU 200 -#define IDS_MENU_QUIT 201 -#define IDS_MENU_KILL_PROCESS 202 - -#define IDS_KILL_PROCESS 1000 -#define IDS_KILL_PROCESS_ERR1 1001 -#define IDS_KILL_PROCESS_ERR2 1002 - -#define IDS_CTM_GENERAL_ERR1 32768 -#define IDS_CTM_GENERAL_ERR2 32769 -#define IDS_CTM_GENERAL_ERR3 32770 +/* + * CTM resource definitions + * + * Copyright 2004 ReactOS team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define IDS_APP_TITLE 0 + +#define IDS_COLUMN_IMAGENAME 10 +#define IDS_COLUMN_PID 11 +#define IDS_COLUMN_CPU 12 +#define IDS_COLUMN_MEM 13 +#define IDS_COLUMN_MEM_UNIT 14 +#define IDS_COLUMN_PF 15 + +#define IDS_IDLE_PROCESS 100 +#define IDS_YES 101 +#define IDS_NO 102 + +#define IDS_MENU 200 +#define IDS_MENU_QUIT 201 +#define IDS_MENU_KILL_PROCESS 202 + +#define IDS_KILL_PROCESS 1000 +#define IDS_KILL_PROCESS_ERR1 1001 +#define IDS_KILL_PROCESS_ERR2 1002 + +#define IDS_CTM_GENERAL_ERR1 32768 +#define IDS_CTM_GENERAL_ERR2 32769 +#define IDS_CTM_GENERAL_ERR3 32770 diff --git a/rosapps/sysutils/dosfsck/boot.c b/rosapps/sysutils/dosfsck/boot.c index cddbac3e1e0..dac2d2c4504 100644 --- a/rosapps/sysutils/dosfsck/boot.c +++ b/rosapps/sysutils/dosfsck/boot.c @@ -1,370 +1,370 @@ -/* boot.c - Read and analyze ia PC/MS-DOS boot sector */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - -#include -#include -#include - -#include "common.h" -#include "dosfsck.h" -#include "io.h" -#include "boot.h" - - -#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) - /* don't divide by zero */ - -static struct { - __u8 media; - char *descr; -} mediabytes[] = { - { 0xf0, "5.25\" or 3.5\" HD floppy" }, - { 0xf8, "hard disk" }, - { 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or " - "5.25\" 1.2M floppy 2s/80tr/15sec" }, - { 0xfa, "5.25\" 320k floppy 1s/80tr/8sec" }, - { 0xfb, "3.5\" 640k floppy 2s/80tr/8sec" }, - { 0xfc, "5.25\" 180k floppy 1s/40tr/9sec" }, - { 0xfd, "5.25\" 360k floppy 2s/40tr/9sec" }, - { 0xfe, "5.25\" 160k floppy 1s/40tr/8sec" }, - { 0xff, "5.25\" 320k floppy 2s/40tr/8sec" }, -}; - -#if defined __alpha || defined __ia64__ || defined __s390x__ || defined __x86_64__ || defined __ppc64__ -/* Unaligned fields must first be copied byte-wise */ -#define GET_UNALIGNED_W(f) \ - ({ \ - unsigned short __v; \ - memcpy( &__v, &f, sizeof(__v) ); \ - CF_LE_W( *(unsigned short *)&f ); \ - }) -#else -#define GET_UNALIGNED_W(f) CF_LE_W( *(unsigned short *)&f ) -#endif - - -static char *get_media_descr( unsigned char media ) -{ - int i; - - for( i = 0; i < sizeof(mediabytes)/sizeof(*mediabytes); ++i ) { - if (mediabytes[i].media == media) - return( mediabytes[i].descr ); - } - return( "undefined" ); -} - -static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss) -{ - unsigned short sectors; - - printf("Boot sector contents:\n"); - if (!atari_format) { - char id[9]; - strncpy(id,b->system_id,8); - id[8] = 0; - printf("System ID \"%s\"\n",id); - } - else { - /* On Atari, a 24 bit serial number is stored at offset 8 of the boot - * sector */ - printf("Serial number 0x%x\n", - b->system_id[5] | (b->system_id[6]<<8) | (b->system_id[7]<<16)); - } - printf("Media byte 0x%02x (%s)\n",b->media,get_media_descr(b->media)); - printf("%10d bytes per logical sector\n",GET_UNALIGNED_W(b->sector_size)); - printf("%10d bytes per cluster\n",fs->cluster_size); - printf("%10d reserved sector%s\n",CF_LE_W(b->reserved), - CF_LE_W(b->reserved) == 1 ? "" : "s"); - printf("First FAT starts at byte %llu (sector %llu)\n", - (__u64)fs->fat_start, - (__u64)fs->fat_start/lss); - printf("%10d FATs, %d bit entries\n",b->fats,fs->fat_bits); - printf("%10d bytes per FAT (= %u sectors)\n",fs->fat_size, - fs->fat_size/lss); - if (!fs->root_cluster) { - printf("Root directory starts at byte %llu (sector %llu)\n", - (__u64)fs->root_start, - (__u64)fs->root_start/lss); - printf("%10d root directory entries\n",fs->root_entries); - } - else { - printf( "Root directory start at cluster %lu (arbitrary size)\n", - fs->root_cluster); - } - printf("Data area starts at byte %llu (sector %llu)\n", - (__u64)fs->data_start, - (__u64)fs->data_start/lss); - printf("%10lu data clusters (%llu bytes)\n",fs->clusters, - (__u64)fs->clusters*fs->cluster_size); - printf("%u sectors/track, %u heads\n",CF_LE_W(b->secs_track), - CF_LE_W(b->heads)); - printf("%10u hidden sectors\n", - atari_format ? - /* On Atari, the hidden field is only 16 bit wide and unused */ - (((unsigned char *)&b->hidden)[0] | - ((unsigned char *)&b->hidden)[1] << 8) : - CF_LE_L(b->hidden)); - sectors = GET_UNALIGNED_W( b->sectors ); - printf("%10u sectors total\n", sectors ? sectors : CF_LE_L(b->total_sect)); -} - -static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss) -{ - struct boot_sector b2; - - if (!fs->backupboot_start) { - printf( "There is no backup boot sector.\n" ); - if (CF_LE_W(b->reserved) < 3) { - printf( "And there is no space for creating one!\n" ); - return; - } - if (interactive) - printf( "1) Create one\n2) Do without a backup\n" ); - else printf( " Auto-creating backup boot block.\n" ); - if (!interactive || get_key("12","?") == '1') { - int bbs; - /* The usual place for the backup boot sector is sector 6. Choose - * that or the last reserved sector. */ - if (CF_LE_W(b->reserved) >= 7 && CF_LE_W(b->info_sector) != 6) - bbs = 6; - else { - bbs = CF_LE_W(b->reserved) - 1; - if (bbs == CF_LE_W(b->info_sector)) - --bbs; /* this is never 0, as we checked reserved >= 3! */ - } - fs->backupboot_start = bbs*lss; - b->backup_boot = CT_LE_W(bbs); - fs_write(fs->backupboot_start,sizeof(*b),b); - fs_write((off_t)offsetof(struct boot_sector,backup_boot), - sizeof(b->backup_boot),&b->backup_boot); - printf( "Created backup of boot sector in sector %d\n", bbs ); - return; - } - else return; - } - - fs_read(fs->backupboot_start,sizeof(b2),&b2); - if (memcmp(b,&b2,sizeof(b2)) != 0) { - /* there are any differences */ - __u8 *p, *q; - int i, pos, first = 1; - char buf[20]; - - printf( "There are differences between boot sector and its backup.\n" ); - printf( "Differences: (offset:original/backup)\n " ); - pos = 2; - for( p = (__u8 *)b, q = (__u8 *)&b2, i = 0; i < sizeof(b2); - ++p, ++q, ++i ) { - if (*p != *q) { - sprintf( buf, "%s%u:%02x/%02x", first ? "" : ", ", - (unsigned)(p-(__u8 *)b), *p, *q ); - if (pos + strlen(buf) > 78) printf( "\n " ), pos = 2; - printf( "%s", buf ); - pos += strlen(buf); - first = 0; - } - } - printf( "\n" ); - - if (interactive) - printf( "1) Copy original to backup\n" - "2) Copy backup to original\n" - "3) No action\n" ); - else printf( " Not automatically fixing this.\n" ); - switch (interactive ? get_key("123","?") : '3') { - case '1': - fs_write(fs->backupboot_start,sizeof(*b),b); - break; - case '2': - fs_write(0,sizeof(b2),&b2); - break; - default: - break; - } - } -} - -static void init_fsinfo(struct info_sector *i) -{ - i->magic = CT_LE_L(0x41615252); - i->signature = CT_LE_L(0x61417272); - i->free_clusters = CT_LE_L(-1); - i->next_cluster = CT_LE_L(2); - i->boot_sign = CT_LE_W(0xaa55); -} - -static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss) -{ - struct info_sector i; - - if (!b->info_sector) { - printf( "No FSINFO sector\n" ); - if (interactive) - printf( "1) Create one\n2) Do without FSINFO\n" ); - else printf( " Not automatically creating it.\n" ); - if (interactive && get_key("12","?") == '1') { - /* search for a free reserved sector (not boot sector and not - * backup boot sector) */ - __u32 s; - for( s = 1; s < CF_LE_W(b->reserved); ++s ) - if (s != CF_LE_W(b->backup_boot)) break; - if (s > 0 && s < CF_LE_W(b->reserved)) { - init_fsinfo(&i); - fs_write((off_t)s*lss,sizeof(i),&i); - b->info_sector = CT_LE_W(s); - fs_write((off_t)offsetof(struct boot_sector,info_sector), - sizeof(b->info_sector),&b->info_sector); - if (fs->backupboot_start) - fs_write(fs->backupboot_start+ - offsetof(struct boot_sector,info_sector), - sizeof(b->info_sector),&b->info_sector); - } - else { - printf( "No free reserved sector found -- " - "no space for FSINFO sector!\n" ); - return; - } - } - else return; - } - - fs->fsinfo_start = CF_LE_W(b->info_sector)*lss; - fs_read(fs->fsinfo_start,sizeof(i),&i); - - if (i.magic != CT_LE_L(0x41615252) || - i.signature != CT_LE_L(0x61417272) || - i.boot_sign != CT_LE_W(0xaa55)) { - printf( "FSINFO sector has bad magic number(s):\n" ); - if (i.magic != CT_LE_L(0x41615252)) - printf( " Offset %llu: 0x%08x != expected 0x%08x\n", - (__u64)offsetof(struct info_sector,magic), - CF_LE_L(i.magic),0x41615252); - if (i.signature != CT_LE_L(0x61417272)) - printf( " Offset %llu: 0x%08x != expected 0x%08x\n", - (__u64)offsetof(struct info_sector,signature), - CF_LE_L(i.signature),0x61417272); - if (i.boot_sign != CT_LE_W(0xaa55)) - printf( " Offset %llu: 0x%04x != expected 0x%04x\n", - (__u64)offsetof(struct info_sector,boot_sign), - CF_LE_W(i.boot_sign),0xaa55); - if (interactive) - printf( "1) Correct\n2) Don't correct (FSINFO invalid then)\n" ); - else printf( " Auto-correcting it.\n" ); - if (!interactive || get_key("12","?") == '1') { - init_fsinfo(&i); - fs_write(fs->fsinfo_start,sizeof(i),&i); - } - else fs->fsinfo_start = 0; - } - - if (fs->fsinfo_start) - fs->free_clusters = CF_LE_L(i.free_clusters); -} - -void read_boot(DOS_FS *fs) -{ - struct boot_sector b; - unsigned total_sectors; - unsigned short logical_sector_size, sectors; - unsigned fat_length; - loff_t data_size; - - fs_read(0,sizeof(b),&b); - logical_sector_size = GET_UNALIGNED_W(b.sector_size); - if (!logical_sector_size) die("Logical sector size is zero."); - fs->cluster_size = b.cluster_size*logical_sector_size; - if (!fs->cluster_size) die("Cluster size is zero."); - if (b.fats != 2 && b.fats != 1) - die("Currently, only 1 or 2 FATs are supported, not %d.\n",b.fats); - fs->nfats = b.fats; - sectors = GET_UNALIGNED_W(b.sectors); - total_sectors = sectors ? sectors : CF_LE_L(b.total_sect); - if (verbose) printf("Checking we can access the last sector of the filesystem\n"); - /* Can't access last odd sector anyway, so round down */ - fs_test((loff_t)((total_sectors & ~1)-1)*(loff_t)logical_sector_size, - logical_sector_size); - fat_length = CF_LE_W(b.fat_length) ? - CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length); - fs->fat_start = (off_t)CF_LE_W(b.reserved)*logical_sector_size; - fs->root_start = ((off_t)CF_LE_W(b.reserved)+b.fats*fat_length)* - logical_sector_size; - fs->root_entries = GET_UNALIGNED_W(b.dir_entries); - fs->data_start = fs->root_start+ROUND_TO_MULTIPLE(fs->root_entries << - MSDOS_DIR_BITS,logical_sector_size); - data_size = (loff_t)total_sectors*logical_sector_size-fs->data_start; - fs->clusters = data_size/fs->cluster_size; - fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */ - fs->fsinfo_start = 0; /* no FSINFO structure */ - fs->free_clusters = -1; /* unknown */ - if (!b.fat_length && b.fat32_length) { - fs->fat_bits = 32; - fs->root_cluster = CF_LE_L(b.root_cluster); - if (!fs->root_cluster && fs->root_entries) - /* M$ hasn't specified this, but it looks reasonable: If - * root_cluster is 0 but there is a separate root dir - * (root_entries != 0), we handle the root dir the old way. Give a - * warning, but convertig to a root dir in a cluster chain seems - * to complex for now... */ - printf( "Warning: FAT32 root dir not in cluster chain! " - "Compability mode...\n" ); - else if (!fs->root_cluster && !fs->root_entries) - die("No root directory!"); - else if (fs->root_cluster && fs->root_entries) - printf( "Warning: FAT32 root dir is in a cluster chain, but " - "a separate root dir\n" - " area is defined. Cannot fix this easily.\n" ); - - fs->backupboot_start = CF_LE_W(b.backup_boot)*logical_sector_size; - check_backup_boot(fs,&b,logical_sector_size); - - read_fsinfo(fs,&b,logical_sector_size); - } - else if (!atari_format) { - /* On real MS-DOS, a 16 bit FAT is used whenever there would be too - * much clusers otherwise. */ - fs->fat_bits = (fs->clusters > MSDOS_FAT12) ? 16 : 12; - } - else { - /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs - * on floppies, and always 16 bit on harddisks. */ - fs->fat_bits = 16; /* assume 16 bit FAT for now */ - /* If more clusters than fat entries in 16-bit fat, we assume - * it's a real MSDOS FS with 12-bit fat. */ - if (fs->clusters+2 > fat_length*logical_sector_size*8/16 || - /* if it's a floppy disk --> 12bit fat */ - device_no == 2 || - /* if it's a ramdisk or loopback device and has one of the usual - * floppy sizes -> 12bit FAT */ - ((device_no == 1 || device_no == 7) && - (total_sectors == 720 || total_sectors == 1440 || - total_sectors == 2880))) - fs->fat_bits = 12; - } - /* On FAT32, the high 4 bits of a FAT entry are reserved */ - fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits; - fs->fat_size = fat_length*logical_sector_size; - if (fs->clusters > ((__u64)fs->fat_size*8/fs->fat_bits)-2) - die("File system has %d clusters but only space for %d FAT entries.", - fs->clusters,((__u64)fs->fat_size*8/fs->fat_bits)-2); - if (!fs->root_entries && !fs->root_cluster) - die("Root directory has zero size."); - if (fs->root_entries & (MSDOS_DPS-1)) - die("Root directory (%d entries) doesn't span an integral number of " - "sectors.",fs->root_entries); - if (logical_sector_size & (SECTOR_SIZE-1)) - die("Logical sector size (%d bytes) is not a multiple of the physical " - "sector size.",logical_sector_size); - /* ++roman: On Atari, these two fields are often left uninitialized */ - if (!atari_format && (!b.secs_track || !b.heads)) - die("Invalid disk format in boot sector."); - if (verbose) dump_boot(fs,&b,logical_sector_size); -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +/* boot.c - Read and analyze ia PC/MS-DOS boot sector */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + +#include +#include +#include + +#include "common.h" +#include "dosfsck.h" +#include "io.h" +#include "boot.h" + + +#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) + /* don't divide by zero */ + +static struct { + __u8 media; + char *descr; +} mediabytes[] = { + { 0xf0, "5.25\" or 3.5\" HD floppy" }, + { 0xf8, "hard disk" }, + { 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or " + "5.25\" 1.2M floppy 2s/80tr/15sec" }, + { 0xfa, "5.25\" 320k floppy 1s/80tr/8sec" }, + { 0xfb, "3.5\" 640k floppy 2s/80tr/8sec" }, + { 0xfc, "5.25\" 180k floppy 1s/40tr/9sec" }, + { 0xfd, "5.25\" 360k floppy 2s/40tr/9sec" }, + { 0xfe, "5.25\" 160k floppy 1s/40tr/8sec" }, + { 0xff, "5.25\" 320k floppy 2s/40tr/8sec" }, +}; + +#if defined __alpha || defined __ia64__ || defined __s390x__ || defined __x86_64__ || defined __ppc64__ +/* Unaligned fields must first be copied byte-wise */ +#define GET_UNALIGNED_W(f) \ + ({ \ + unsigned short __v; \ + memcpy( &__v, &f, sizeof(__v) ); \ + CF_LE_W( *(unsigned short *)&f ); \ + }) +#else +#define GET_UNALIGNED_W(f) CF_LE_W( *(unsigned short *)&f ) +#endif + + +static char *get_media_descr( unsigned char media ) +{ + int i; + + for( i = 0; i < sizeof(mediabytes)/sizeof(*mediabytes); ++i ) { + if (mediabytes[i].media == media) + return( mediabytes[i].descr ); + } + return( "undefined" ); +} + +static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss) +{ + unsigned short sectors; + + printf("Boot sector contents:\n"); + if (!atari_format) { + char id[9]; + strncpy(id,b->system_id,8); + id[8] = 0; + printf("System ID \"%s\"\n",id); + } + else { + /* On Atari, a 24 bit serial number is stored at offset 8 of the boot + * sector */ + printf("Serial number 0x%x\n", + b->system_id[5] | (b->system_id[6]<<8) | (b->system_id[7]<<16)); + } + printf("Media byte 0x%02x (%s)\n",b->media,get_media_descr(b->media)); + printf("%10d bytes per logical sector\n",GET_UNALIGNED_W(b->sector_size)); + printf("%10d bytes per cluster\n",fs->cluster_size); + printf("%10d reserved sector%s\n",CF_LE_W(b->reserved), + CF_LE_W(b->reserved) == 1 ? "" : "s"); + printf("First FAT starts at byte %llu (sector %llu)\n", + (__u64)fs->fat_start, + (__u64)fs->fat_start/lss); + printf("%10d FATs, %d bit entries\n",b->fats,fs->fat_bits); + printf("%10d bytes per FAT (= %u sectors)\n",fs->fat_size, + fs->fat_size/lss); + if (!fs->root_cluster) { + printf("Root directory starts at byte %llu (sector %llu)\n", + (__u64)fs->root_start, + (__u64)fs->root_start/lss); + printf("%10d root directory entries\n",fs->root_entries); + } + else { + printf( "Root directory start at cluster %lu (arbitrary size)\n", + fs->root_cluster); + } + printf("Data area starts at byte %llu (sector %llu)\n", + (__u64)fs->data_start, + (__u64)fs->data_start/lss); + printf("%10lu data clusters (%llu bytes)\n",fs->clusters, + (__u64)fs->clusters*fs->cluster_size); + printf("%u sectors/track, %u heads\n",CF_LE_W(b->secs_track), + CF_LE_W(b->heads)); + printf("%10u hidden sectors\n", + atari_format ? + /* On Atari, the hidden field is only 16 bit wide and unused */ + (((unsigned char *)&b->hidden)[0] | + ((unsigned char *)&b->hidden)[1] << 8) : + CF_LE_L(b->hidden)); + sectors = GET_UNALIGNED_W( b->sectors ); + printf("%10u sectors total\n", sectors ? sectors : CF_LE_L(b->total_sect)); +} + +static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss) +{ + struct boot_sector b2; + + if (!fs->backupboot_start) { + printf( "There is no backup boot sector.\n" ); + if (CF_LE_W(b->reserved) < 3) { + printf( "And there is no space for creating one!\n" ); + return; + } + if (interactive) + printf( "1) Create one\n2) Do without a backup\n" ); + else printf( " Auto-creating backup boot block.\n" ); + if (!interactive || get_key("12","?") == '1') { + int bbs; + /* The usual place for the backup boot sector is sector 6. Choose + * that or the last reserved sector. */ + if (CF_LE_W(b->reserved) >= 7 && CF_LE_W(b->info_sector) != 6) + bbs = 6; + else { + bbs = CF_LE_W(b->reserved) - 1; + if (bbs == CF_LE_W(b->info_sector)) + --bbs; /* this is never 0, as we checked reserved >= 3! */ + } + fs->backupboot_start = bbs*lss; + b->backup_boot = CT_LE_W(bbs); + fs_write(fs->backupboot_start,sizeof(*b),b); + fs_write((off_t)offsetof(struct boot_sector,backup_boot), + sizeof(b->backup_boot),&b->backup_boot); + printf( "Created backup of boot sector in sector %d\n", bbs ); + return; + } + else return; + } + + fs_read(fs->backupboot_start,sizeof(b2),&b2); + if (memcmp(b,&b2,sizeof(b2)) != 0) { + /* there are any differences */ + __u8 *p, *q; + int i, pos, first = 1; + char buf[20]; + + printf( "There are differences between boot sector and its backup.\n" ); + printf( "Differences: (offset:original/backup)\n " ); + pos = 2; + for( p = (__u8 *)b, q = (__u8 *)&b2, i = 0; i < sizeof(b2); + ++p, ++q, ++i ) { + if (*p != *q) { + sprintf( buf, "%s%u:%02x/%02x", first ? "" : ", ", + (unsigned)(p-(__u8 *)b), *p, *q ); + if (pos + strlen(buf) > 78) printf( "\n " ), pos = 2; + printf( "%s", buf ); + pos += strlen(buf); + first = 0; + } + } + printf( "\n" ); + + if (interactive) + printf( "1) Copy original to backup\n" + "2) Copy backup to original\n" + "3) No action\n" ); + else printf( " Not automatically fixing this.\n" ); + switch (interactive ? get_key("123","?") : '3') { + case '1': + fs_write(fs->backupboot_start,sizeof(*b),b); + break; + case '2': + fs_write(0,sizeof(b2),&b2); + break; + default: + break; + } + } +} + +static void init_fsinfo(struct info_sector *i) +{ + i->magic = CT_LE_L(0x41615252); + i->signature = CT_LE_L(0x61417272); + i->free_clusters = CT_LE_L(-1); + i->next_cluster = CT_LE_L(2); + i->boot_sign = CT_LE_W(0xaa55); +} + +static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss) +{ + struct info_sector i; + + if (!b->info_sector) { + printf( "No FSINFO sector\n" ); + if (interactive) + printf( "1) Create one\n2) Do without FSINFO\n" ); + else printf( " Not automatically creating it.\n" ); + if (interactive && get_key("12","?") == '1') { + /* search for a free reserved sector (not boot sector and not + * backup boot sector) */ + __u32 s; + for( s = 1; s < CF_LE_W(b->reserved); ++s ) + if (s != CF_LE_W(b->backup_boot)) break; + if (s > 0 && s < CF_LE_W(b->reserved)) { + init_fsinfo(&i); + fs_write((off_t)s*lss,sizeof(i),&i); + b->info_sector = CT_LE_W(s); + fs_write((off_t)offsetof(struct boot_sector,info_sector), + sizeof(b->info_sector),&b->info_sector); + if (fs->backupboot_start) + fs_write(fs->backupboot_start+ + offsetof(struct boot_sector,info_sector), + sizeof(b->info_sector),&b->info_sector); + } + else { + printf( "No free reserved sector found -- " + "no space for FSINFO sector!\n" ); + return; + } + } + else return; + } + + fs->fsinfo_start = CF_LE_W(b->info_sector)*lss; + fs_read(fs->fsinfo_start,sizeof(i),&i); + + if (i.magic != CT_LE_L(0x41615252) || + i.signature != CT_LE_L(0x61417272) || + i.boot_sign != CT_LE_W(0xaa55)) { + printf( "FSINFO sector has bad magic number(s):\n" ); + if (i.magic != CT_LE_L(0x41615252)) + printf( " Offset %llu: 0x%08x != expected 0x%08x\n", + (__u64)offsetof(struct info_sector,magic), + CF_LE_L(i.magic),0x41615252); + if (i.signature != CT_LE_L(0x61417272)) + printf( " Offset %llu: 0x%08x != expected 0x%08x\n", + (__u64)offsetof(struct info_sector,signature), + CF_LE_L(i.signature),0x61417272); + if (i.boot_sign != CT_LE_W(0xaa55)) + printf( " Offset %llu: 0x%04x != expected 0x%04x\n", + (__u64)offsetof(struct info_sector,boot_sign), + CF_LE_W(i.boot_sign),0xaa55); + if (interactive) + printf( "1) Correct\n2) Don't correct (FSINFO invalid then)\n" ); + else printf( " Auto-correcting it.\n" ); + if (!interactive || get_key("12","?") == '1') { + init_fsinfo(&i); + fs_write(fs->fsinfo_start,sizeof(i),&i); + } + else fs->fsinfo_start = 0; + } + + if (fs->fsinfo_start) + fs->free_clusters = CF_LE_L(i.free_clusters); +} + +void read_boot(DOS_FS *fs) +{ + struct boot_sector b; + unsigned total_sectors; + unsigned short logical_sector_size, sectors; + unsigned fat_length; + loff_t data_size; + + fs_read(0,sizeof(b),&b); + logical_sector_size = GET_UNALIGNED_W(b.sector_size); + if (!logical_sector_size) die("Logical sector size is zero."); + fs->cluster_size = b.cluster_size*logical_sector_size; + if (!fs->cluster_size) die("Cluster size is zero."); + if (b.fats != 2 && b.fats != 1) + die("Currently, only 1 or 2 FATs are supported, not %d.\n",b.fats); + fs->nfats = b.fats; + sectors = GET_UNALIGNED_W(b.sectors); + total_sectors = sectors ? sectors : CF_LE_L(b.total_sect); + if (verbose) printf("Checking we can access the last sector of the filesystem\n"); + /* Can't access last odd sector anyway, so round down */ + fs_test((loff_t)((total_sectors & ~1)-1)*(loff_t)logical_sector_size, + logical_sector_size); + fat_length = CF_LE_W(b.fat_length) ? + CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length); + fs->fat_start = (off_t)CF_LE_W(b.reserved)*logical_sector_size; + fs->root_start = ((off_t)CF_LE_W(b.reserved)+b.fats*fat_length)* + logical_sector_size; + fs->root_entries = GET_UNALIGNED_W(b.dir_entries); + fs->data_start = fs->root_start+ROUND_TO_MULTIPLE(fs->root_entries << + MSDOS_DIR_BITS,logical_sector_size); + data_size = (loff_t)total_sectors*logical_sector_size-fs->data_start; + fs->clusters = data_size/fs->cluster_size; + fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */ + fs->fsinfo_start = 0; /* no FSINFO structure */ + fs->free_clusters = -1; /* unknown */ + if (!b.fat_length && b.fat32_length) { + fs->fat_bits = 32; + fs->root_cluster = CF_LE_L(b.root_cluster); + if (!fs->root_cluster && fs->root_entries) + /* M$ hasn't specified this, but it looks reasonable: If + * root_cluster is 0 but there is a separate root dir + * (root_entries != 0), we handle the root dir the old way. Give a + * warning, but convertig to a root dir in a cluster chain seems + * to complex for now... */ + printf( "Warning: FAT32 root dir not in cluster chain! " + "Compability mode...\n" ); + else if (!fs->root_cluster && !fs->root_entries) + die("No root directory!"); + else if (fs->root_cluster && fs->root_entries) + printf( "Warning: FAT32 root dir is in a cluster chain, but " + "a separate root dir\n" + " area is defined. Cannot fix this easily.\n" ); + + fs->backupboot_start = CF_LE_W(b.backup_boot)*logical_sector_size; + check_backup_boot(fs,&b,logical_sector_size); + + read_fsinfo(fs,&b,logical_sector_size); + } + else if (!atari_format) { + /* On real MS-DOS, a 16 bit FAT is used whenever there would be too + * much clusers otherwise. */ + fs->fat_bits = (fs->clusters > MSDOS_FAT12) ? 16 : 12; + } + else { + /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs + * on floppies, and always 16 bit on harddisks. */ + fs->fat_bits = 16; /* assume 16 bit FAT for now */ + /* If more clusters than fat entries in 16-bit fat, we assume + * it's a real MSDOS FS with 12-bit fat. */ + if (fs->clusters+2 > fat_length*logical_sector_size*8/16 || + /* if it's a floppy disk --> 12bit fat */ + device_no == 2 || + /* if it's a ramdisk or loopback device and has one of the usual + * floppy sizes -> 12bit FAT */ + ((device_no == 1 || device_no == 7) && + (total_sectors == 720 || total_sectors == 1440 || + total_sectors == 2880))) + fs->fat_bits = 12; + } + /* On FAT32, the high 4 bits of a FAT entry are reserved */ + fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits; + fs->fat_size = fat_length*logical_sector_size; + if (fs->clusters > ((__u64)fs->fat_size*8/fs->fat_bits)-2) + die("File system has %d clusters but only space for %d FAT entries.", + fs->clusters,((__u64)fs->fat_size*8/fs->fat_bits)-2); + if (!fs->root_entries && !fs->root_cluster) + die("Root directory has zero size."); + if (fs->root_entries & (MSDOS_DPS-1)) + die("Root directory (%d entries) doesn't span an integral number of " + "sectors.",fs->root_entries); + if (logical_sector_size & (SECTOR_SIZE-1)) + die("Logical sector size (%d bytes) is not a multiple of the physical " + "sector size.",logical_sector_size); + /* ++roman: On Atari, these two fields are often left uninitialized */ + if (!atari_format && (!b.secs_track || !b.heads)) + die("Invalid disk format in boot sector."); + if (verbose) dump_boot(fs,&b,logical_sector_size); +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/boot.h b/rosapps/sysutils/dosfsck/boot.h index 63cbcf01995..0540c701662 100644 --- a/rosapps/sysutils/dosfsck/boot.h +++ b/rosapps/sysutils/dosfsck/boot.h @@ -1,13 +1,13 @@ -/* boot.h - Read and analyze ia PC/MS-DOS boot sector */ - -/* Written 1993 by Werner Almesberger */ - - -#ifndef _BOOT_H -#define _BOOT_H - -void read_boot(DOS_FS *fs); - -/* Reads the boot sector from the currently open device and initializes *FS */ - -#endif +/* boot.h - Read and analyze ia PC/MS-DOS boot sector */ + +/* Written 1993 by Werner Almesberger */ + + +#ifndef _BOOT_H +#define _BOOT_H + +void read_boot(DOS_FS *fs); + +/* Reads the boot sector from the currently open device and initializes *FS */ + +#endif diff --git a/rosapps/sysutils/dosfsck/byteorder.h b/rosapps/sysutils/dosfsck/byteorder.h index 15b87c09e18..07ab6ebfaac 100644 --- a/rosapps/sysutils/dosfsck/byteorder.h +++ b/rosapps/sysutils/dosfsck/byteorder.h @@ -1,59 +1,59 @@ -#ifndef _I386_BYTEORDER_H -#define _I386_BYTEORDER_H - -//#include "types.h" -#include "compiler.h" - -#ifdef __GNUC__ - -/* For avoiding bswap on i386 */ -//#ifdef __KERNEL__ -//#include -//#endif - -static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) -{ -#ifdef CONFIG_X86_BSWAP - __asm__("bswap %0" : "=r" (x) : "0" (x)); -#else - __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ - "rorl $16,%0\n\t" /* swap words */ - "xchgb %b0,%h0" /* swap higher bytes */ - :"=q" (x) - : "0" (x)); -#endif - return x; -} - -static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val) -{ - union { - struct { __u32 a,b; } s; - __u64 u; - } v; - v.u = val; -#ifdef CONFIG_X86_BSWAP - asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1" - : "=r" (v.s.a), "=r" (v.s.b) - : "0" (v.s.a), "1" (v.s.b)); -#else - v.s.a = ___arch__swab32(v.s.a); - v.s.b = ___arch__swab32(v.s.b); - asm("xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b) : "0" (v.s.a), "1" (v.s.b)); -#endif - return v.u; -} - -/* Do not define swab16. Gcc is smart enough to recognize "C" version and - convert it into rotation or exhange. */ - -#define __arch__swab64(x) ___arch__swab64(x) -#define __arch__swab32(x) ___arch__swab32(x) - -#define __BYTEORDER_HAS_U64__ - -#endif /* __GNUC__ */ - -//#include "little_endian.h" - -#endif /* _I386_BYTEORDER_H */ +#ifndef _I386_BYTEORDER_H +#define _I386_BYTEORDER_H + +//#include "types.h" +#include "compiler.h" + +#ifdef __GNUC__ + +/* For avoiding bswap on i386 */ +//#ifdef __KERNEL__ +//#include +//#endif + +static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) +{ +#ifdef CONFIG_X86_BSWAP + __asm__("bswap %0" : "=r" (x) : "0" (x)); +#else + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ + "rorl $16,%0\n\t" /* swap words */ + "xchgb %b0,%h0" /* swap higher bytes */ + :"=q" (x) + : "0" (x)); +#endif + return x; +} + +static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val) +{ + union { + struct { __u32 a,b; } s; + __u64 u; + } v; + v.u = val; +#ifdef CONFIG_X86_BSWAP + asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1" + : "=r" (v.s.a), "=r" (v.s.b) + : "0" (v.s.a), "1" (v.s.b)); +#else + v.s.a = ___arch__swab32(v.s.a); + v.s.b = ___arch__swab32(v.s.b); + asm("xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b) : "0" (v.s.a), "1" (v.s.b)); +#endif + return v.u; +} + +/* Do not define swab16. Gcc is smart enough to recognize "C" version and + convert it into rotation or exhange. */ + +#define __arch__swab64(x) ___arch__swab64(x) +#define __arch__swab32(x) ___arch__swab32(x) + +#define __BYTEORDER_HAS_U64__ + +#endif /* __GNUC__ */ + +//#include "little_endian.h" + +#endif /* _I386_BYTEORDER_H */ diff --git a/rosapps/sysutils/dosfsck/byteswap.h b/rosapps/sysutils/dosfsck/byteswap.h index 4a09eb6d68f..0cf37c16848 100644 --- a/rosapps/sysutils/dosfsck/byteswap.h +++ b/rosapps/sysutils/dosfsck/byteswap.h @@ -1,40 +1,40 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _BYTESWAP_H -#define _BYTESWAP_H 1 - -/* Get the machine specific, optimized definitions. */ -#include "byteswap1.h" - - -/* The following definitions must all be macros since otherwise some - of the possible optimizations are not possible. */ - -/* Return a value with all bytes in the 16 bit argument swapped. */ -#define bswap_16(x) __bswap_16 (x) - -/* Return a value with all bytes in the 32 bit argument swapped. */ -#define bswap_32(x) __bswap_32 (x) - -#if defined __GNUC__ && __GNUC__ >= 2 -/* Return a value with all bytes in the 64 bit argument swapped. */ -# define bswap_64(x) __bswap_64 (x) -#endif - -#endif /* byteswap.h */ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BYTESWAP_H +#define _BYTESWAP_H 1 + +/* Get the machine specific, optimized definitions. */ +#include "byteswap1.h" + + +/* The following definitions must all be macros since otherwise some + of the possible optimizations are not possible. */ + +/* Return a value with all bytes in the 16 bit argument swapped. */ +#define bswap_16(x) __bswap_16 (x) + +/* Return a value with all bytes in the 32 bit argument swapped. */ +#define bswap_32(x) __bswap_32 (x) + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Return a value with all bytes in the 64 bit argument swapped. */ +# define bswap_64(x) __bswap_64 (x) +#endif + +#endif /* byteswap.h */ diff --git a/rosapps/sysutils/dosfsck/byteswap1.h b/rosapps/sysutils/dosfsck/byteswap1.h index 1e5d4666134..33af2088883 100644 --- a/rosapps/sysutils/dosfsck/byteswap1.h +++ b/rosapps/sysutils/dosfsck/byteswap1.h @@ -1,133 +1,133 @@ -/* Macros to swap the order of bytes in integer values. - Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#if !defined _BYTESWAP_H && !defined _NETINET_IN_H -# error "Never use directly; include instead." -#endif - -#ifndef _BITS_BYTESWAP_H -#define _BITS_BYTESWAP_H 1 - -/* Swap bytes in 16 bit value. */ -#define __bswap_constant_16(x) \ - ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) - -#ifdef __GNUC__ -# if __GNUC__ >= 2 -# define __bswap_16(x) \ - (__extension__ \ - ({ register unsigned short int __v, __x = (x); \ - if (__builtin_constant_p (__x)) \ - __v = __bswap_constant_16 (__x); \ - else \ - __asm__ ("rorw $8, %w0" \ - : "=r" (__v) \ - : "0" (__x) \ - : "cc"); \ - __v; })) -# else -/* This is better than nothing. */ -# define __bswap_16(x) \ - (__extension__ \ - ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); })) -# endif -#else -static __inline unsigned short int -__bswap_16 (unsigned short int __bsx) -{ - return __bswap_constant_16 (__bsx); -} -#endif - -/* Swap bytes in 32 bit value. */ -#define __bswap_constant_32(x) \ - ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ - (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) - -#ifdef __GNUC__ -# if __GNUC__ >= 2 -/* To swap the bytes in a word the i486 processors and up provide the - `bswap' opcode. On i386 we have to use three instructions. */ -# if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \ - && !defined __pentium4__ -# define __bswap_32(x) \ - (__extension__ \ - ({ register unsigned int __v, __x = (x); \ - if (__builtin_constant_p (__x)) \ - __v = __bswap_constant_32 (__x); \ - else \ - __asm__ ("rorw $8, %w0;" \ - "rorl $16, %0;" \ - "rorw $8, %w0" \ - : "=r" (__v) \ - : "0" (__x) \ - : "cc"); \ - __v; })) -# else -# define __bswap_32(x) \ - (__extension__ \ - ({ register unsigned int __v, __x = (x); \ - if (__builtin_constant_p (__x)) \ - __v = __bswap_constant_32 (__x); \ - else \ - __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \ - __v; })) -# endif -# else -# define __bswap_32(x) \ - (__extension__ \ - ({ register unsigned int __x = (x); __bswap_constant_32 (__x); })) -# endif -#else -static __inline unsigned int -__bswap_32 (unsigned int __bsx) -{ - return __bswap_constant_32 (__bsx); -} -#endif - - -#if defined __GNUC__ && __GNUC__ >= 2 -/* Swap bytes in 64 bit value. */ -#define __bswap_constant_64(x) \ - ((((x) & 0xff00000000000000ull) >> 56) \ - | (((x) & 0x00ff000000000000ull) >> 40) \ - | (((x) & 0x0000ff0000000000ull) >> 24) \ - | (((x) & 0x000000ff00000000ull) >> 8) \ - | (((x) & 0x00000000ff000000ull) << 8) \ - | (((x) & 0x0000000000ff0000ull) << 24) \ - | (((x) & 0x000000000000ff00ull) << 40) \ - | (((x) & 0x00000000000000ffull) << 56)) - -# define __bswap_64(x) \ - (__extension__ \ - ({ union { __extension__ unsigned long long int __ll; \ - unsigned long int __l[2]; } __w, __r; \ - if (__builtin_constant_p (x)) \ - __r.__ll = __bswap_constant_64 (x); \ - else \ - { \ - __w.__ll = (x); \ - __r.__l[0] = __bswap_32 (__w.__l[1]); \ - __r.__l[1] = __bswap_32 (__w.__l[0]); \ - } \ - __r.__ll; })) -#endif - -#endif /* _BITS_BYTESWAP_H */ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +#ifdef __GNUC__ +# if __GNUC__ >= 2 +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_16 (__x); \ + else \ + __asm__ ("rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# else +/* This is better than nothing. */ +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); })) +# endif +#else +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return __bswap_constant_16 (__bsx); +} +#endif + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#ifdef __GNUC__ +# if __GNUC__ >= 2 +/* To swap the bytes in a word the i486 processors and up provide the + `bswap' opcode. On i386 we have to use three instructions. */ +# if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \ + && !defined __pentium4__ +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("rorw $8, %w0;" \ + "rorl $16, %0;" \ + "rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \ + __v; })) +# endif +# else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __x = (x); __bswap_constant_32 (__x); })) +# endif +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return __bswap_constant_32 (__bsx); +} +#endif + + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +#define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# define __bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned long int __l[2]; } __w, __r; \ + if (__builtin_constant_p (x)) \ + __r.__ll = __bswap_constant_64 (x); \ + else \ + { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + } \ + __r.__ll; })) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/rosapps/sysutils/dosfsck/check.c b/rosapps/sysutils/dosfsck/check.c index 425bd208461..624aaf48d85 100644 --- a/rosapps/sysutils/dosfsck/check.c +++ b/rosapps/sysutils/dosfsck/check.c @@ -1,867 +1,867 @@ -/* check.c - Check and repair a PC/MS-DOS file system */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "dosfsck.h" -#include "io.h" -#include "fat.h" -#include "file.h" -#include "lfn.h" -#include "check.h" - - -static DOS_FILE *root; - -/* get start field of a dir entry */ -#define FSTART(p,fs) \ - ((unsigned long)CF_LE_W(p->dir_ent.start) | \ - (fs->fat_bits == 32 ? CF_LE_W(p->dir_ent.starthi) << 16 : 0)) - -#define MODIFY(p,i,v) \ - do { \ - if (p->offset) { \ - p->dir_ent.i = v; \ - fs_write(p->offset+offsetof(DIR_ENT,i), \ - sizeof(p->dir_ent.i),&p->dir_ent.i); \ - } \ - } while(0) - -#define MODIFY_START(p,v,fs) \ - do { \ - unsigned long __v = (v); \ - if (!p->offset) { \ - /* writing to fake entry for FAT32 root dir */ \ - if (!__v) die("Oops, deleting FAT32 root dir!"); \ - fs->root_cluster = __v; \ - p->dir_ent.start = CT_LE_W(__v&0xffff); \ - p->dir_ent.starthi = CT_LE_W(__v>>16); \ - __v = CT_LE_L(__v); \ - fs_write((loff_t)offsetof(struct boot_sector,root_cluster), \ - sizeof(((struct boot_sector *)0)->root_cluster), \ - &__v); \ - } \ - else { \ - MODIFY(p,start,CT_LE_W((__v)&0xffff)); \ - if (fs->fat_bits == 32) \ - MODIFY(p,starthi,CT_LE_W((__v)>>16)); \ - } \ - } while(0) - - -loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern) -{ - static int curr_num = 0; - loff_t offset; - - if (fs->root_cluster) { - DIR_ENT d2; - int i = 0, got = 0; - unsigned long clu_num, prev = 0; - loff_t offset2; - - clu_num = fs->root_cluster; - offset = cluster_start(fs,clu_num); - while (clu_num > 0 && clu_num != -1) { - fs_read(offset,sizeof(DIR_ENT),&d2); - if (IS_FREE(d2.name) && d2.attr != VFAT_LN_ATTR) { - got = 1; - break; - } - i += sizeof(DIR_ENT); - offset += sizeof(DIR_ENT); - if ((i % fs->cluster_size) == 0) { - prev = clu_num; - if ((clu_num = next_cluster(fs,clu_num)) == 0 || clu_num == -1) - break; - offset = cluster_start(fs,clu_num); - } - } - if (!got) { - /* no free slot, need to extend root dir: alloc next free cluster - * after previous one */ - if (!prev) - die("Root directory has no cluster allocated!"); - for (clu_num = prev+1; clu_num != prev; clu_num++) { - if (clu_num >= fs->clusters+2) clu_num = 2; - if (!fs->fat[clu_num].value) - break; - } - if (clu_num == prev) - die("Root directory full and no free cluster"); - set_fat(fs,prev,clu_num); - set_fat(fs,clu_num,-1); - set_owner(fs, clu_num, get_owner(fs, fs->root_cluster)); - /* clear new cluster */ - memset( &d2, 0, sizeof(d2) ); - offset = cluster_start(fs,clu_num); - for( i = 0; i < (int)fs->cluster_size; i += sizeof(DIR_ENT) ) - fs_write( offset+i, sizeof(d2), &d2 ); - } - memset(de,0,sizeof(DIR_ENT)); - while (1) { - sprintf(de->name,pattern,curr_num); - clu_num = fs->root_cluster; - i = 0; - offset2 = cluster_start(fs,clu_num); - while (clu_num > 0 && clu_num != -1) { - fs_read(offset2,sizeof(DIR_ENT),&d2); - if (offset2 != offset && - !strncmp(d2.name,de->name,MSDOS_NAME)) - break; - i += sizeof(DIR_ENT); - offset2 += sizeof(DIR_ENT); - if ((i % fs->cluster_size) == 0) { - if ((clu_num = next_cluster(fs,clu_num)) == 0 || - clu_num == -1) - break; - offset2 = cluster_start(fs,clu_num); - } - } - if (clu_num == 0 || clu_num == -1) - break; - if (++curr_num >= 10000) die("Unable to create unique name"); - } - } - else { - DIR_ENT *root; - int next_free = 0, scan; - - root = alloc(fs->root_entries*sizeof(DIR_ENT)); - fs_read(fs->root_start,fs->root_entries*sizeof(DIR_ENT),root); - - while (next_free < (int)fs->root_entries) - if (IS_FREE(root[next_free].name) && - root[next_free].attr != VFAT_LN_ATTR) - break; - else next_free++; - if (next_free == (int)fs->root_entries) - die("Root directory is full."); - offset = fs->root_start+next_free*sizeof(DIR_ENT); - memset(de,0,sizeof(DIR_ENT)); - while (1) { - sprintf(de->name,pattern,curr_num); - for (scan = 0; scan < (int)fs->root_entries; scan++) - if (scan != next_free && - !strncmp(root[scan].name,de->name,MSDOS_NAME)) - break; - if (scan == (int)fs->root_entries) break; - if (++curr_num >= 10000) die("Unable to create unique name"); - } - free(root); - } - ++n_files; - return offset; -} - - -static char *path_name(DOS_FILE *file) -{ -// static char path[PATH_MAX*2]; - static char path[MAX_PATH*2]; - - if (!file) *path = 0; - else { - if (strlen(path_name(file->parent)) > MAX_PATH) - die("Path name too long."); - if (strcmp(path,"/") != 0) strcat(path,"/"); - strcpy(strrchr(path,0),file->lfn?file->lfn:file_name(file->dir_ent.name)); - } - return path; -} - - -static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; - /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */ - - -/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ - -time_t date_dos2unix(unsigned short time,unsigned short date) -{ - int month,year; - time_t secs; - - month = ((date >> 5) & 15)-1; - year = date >> 9; - secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* - ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && - month < 2 ? 1 : 0)+3653); - /* days since 1.1.70 plus 80's leap day */ - return secs; -} - - -static char *file_stat(DOS_FILE *file) -{ - static char temp[100]; - struct tm *tm; - char tmp[100]; - time_t date; - - date = date_dos2unix(CF_LE_W(file->dir_ent.time),CF_LE_W(file-> - dir_ent.date)); - tm = localtime(&date); - strftime(tmp,99,"%H:%M:%S %b %d %Y",tm); - sprintf(temp," Size %u bytes, date %s",CF_LE_L(file->dir_ent.size),tmp); - return temp; -} - - -static int bad_name(unsigned char *name) -{ - int i, spc, suspicious = 0; - char *bad_chars = atari_format ? "*?\\/:" : "*?<>|\"\\/:"; - - /* Do not complain about (and auto-correct) the extended attribute files - * of OS/2. */ - if (strncmp(name,"EA DATA SF",11) == 0 || - strncmp(name,"WP ROOT SF",11) == 0) return 0; - - for (i = 0; i < 8; i++) { - if (name[i] < ' ' || name[i] == 0x7f) return 1; - if (name[i] > 0x7f) ++suspicious; - if (strchr(bad_chars,name[i])) return 1; - } - - for (i = 8; i < 11; i++) { - if (name[i] < ' ' || name[i] == 0x7f) return 1; - if (name[i] > 0x7f) ++suspicious; - if (strchr(bad_chars,name[i])) return 1; - } - - spc = 0; - for (i = 0; i < 8; i++) { - if (name[i] == ' ') - spc = 1; - else if (spc) - /* non-space after a space not allowed, space terminates the name - * part */ - return 1; - } - - spc = 0; - for (i = 8; i < 11; i++) { - if (name[i] == ' ') - spc = 1; - else if (spc) - /* non-space after a space not allowed, space terminates the name - * part */ - return 1; - } - - /* Under GEMDOS, chars >= 128 are never allowed. */ - if (atari_format && suspicious) - return 1; - - /* Only complain about too much suspicious chars in interactive mode, - * never correct them automatically. The chars are all basically ok, so we - * shouldn't auto-correct such names. */ - if (interactive && suspicious > 6) - return 1; - return 0; -} - - -static void drop_file(DOS_FS *fs,DOS_FILE *file) -{ - unsigned long cluster; - - MODIFY(file,name[0],DELETED_FLAG); - for (cluster = FSTART(file,fs); cluster > 0 && cluster < - fs->clusters+2; cluster = next_cluster(fs,cluster)) - set_owner(fs,cluster,NULL); - --n_files; -} - - -static void truncate_file(DOS_FS *fs,DOS_FILE *file,unsigned long clusters) -{ - int deleting; - unsigned long walk,next,prev; - - walk = FSTART(file,fs); - prev = 0; - if ((deleting = !clusters)) MODIFY_START(file,0,fs); - while (walk > 0 && walk != -1) { - next = next_cluster(fs,walk); - if (deleting) set_fat(fs,walk,0); - else if ((deleting = !--clusters)) set_fat(fs,walk,-1); - prev = walk; - walk = next; - } -} - - -static void auto_rename(DOS_FILE *file) -{ - DOS_FILE *first,*walk; - int number; - - if (!file->offset) return; /* cannot rename FAT32 root dir */ - first = file->parent ? file->parent->first : root; - number = 0; - while (1) { - sprintf(file->dir_ent.name,"FSCK%04d",number); - strncpy(file->dir_ent.ext,"REN",3); - for (walk = first; walk; walk = walk->next) - if (walk != file && !strncmp(walk->dir_ent.name,file->dir_ent. - name,MSDOS_NAME)) break; - if (!walk) { - fs_write(file->offset,MSDOS_NAME,file->dir_ent.name); - return; - } - number++; - } - die("Can't generate a unique name."); -} - - -static void rename_file(DOS_FILE *file) -{ - unsigned char name[46]; - unsigned char *walk,*here; - - if (!file->offset) { - printf( "Cannot rename FAT32 root dir\n" ); - return; /* cannot rename FAT32 root dir */ - } - while (1) { - printf("New name: "); - fflush(stdout); - if (fgets(name,45,stdin)) { - if ((here = strchr(name,'\n'))) *here = 0; - for (walk = strrchr(name,0); walk >= name && (*walk == ' ' || - *walk == '\t'); walk--); - walk[1] = 0; - for (walk = name; *walk == ' ' || *walk == '\t'; walk++); - if (file_cvt(walk,file->dir_ent.name)) { - fs_write(file->offset,MSDOS_NAME,file->dir_ent.name); - return; - } - } - } -} - - -static int handle_dot(DOS_FS *fs,DOS_FILE *file,int dots) -{ - char *name; - - name = strncmp(file->dir_ent.name,MSDOS_DOT,MSDOS_NAME) ? ".." : "."; - if (!(file->dir_ent.attr & ATTR_DIR)) { - printf("%s\n Is a non-directory.\n",path_name(file)); - if (interactive) - printf("1) Drop it\n2) Auto-rename\n3) Rename\n" - "4) Convert to directory\n"); - else printf(" Auto-renaming it.\n"); - switch (interactive ? get_key("1234","?") : '2') { - case '1': - drop_file(fs,file); - return 1; - case '2': - auto_rename(file); - printf(" Renamed to %s\n",file_name(file->dir_ent.name)); - return 0; - case '3': - rename_file(file); - return 0; - case '4': - MODIFY(file,size,CT_LE_L(0)); - MODIFY(file,attr,file->dir_ent.attr | ATTR_DIR); - break; - } - } - if (!dots) { - printf("Root contains directory \"%s\". Dropping it.\n",name); - drop_file(fs,file); - return 1; - } - return 0; -} - - -static int check_file(DOS_FS *fs,DOS_FILE *file) -{ - DOS_FILE *owner; - int restart; - unsigned long expect,curr,this,clusters,prev,walk,clusters2; - - if (file->dir_ent.attr & ATTR_DIR) { - if (CF_LE_L(file->dir_ent.size)) { - printf("%s\n Directory has non-zero size. Fixing it.\n", - path_name(file)); - MODIFY(file,size,CT_LE_L(0)); - } - if (file->parent && !strncmp(file->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) { - expect = FSTART(file->parent,fs); - if (FSTART(file,fs) != expect) { - printf("%s\n Start (%ld) does not point to parent (%ld)\n", - path_name(file),FSTART(file,fs),expect); - MODIFY_START(file,expect,fs); - } - return 0; - } - if (file->parent && !strncmp(file->dir_ent.name,MSDOS_DOTDOT, - MSDOS_NAME)) { - expect = file->parent->parent ? FSTART(file->parent->parent,fs):0; - if (fs->root_cluster && expect == fs->root_cluster) - expect = 0; - if (FSTART(file,fs) != expect) { - printf("%s\n Start (%lu) does not point to .. (%lu)\n", - path_name(file),FSTART(file,fs),expect); - MODIFY_START(file,expect,fs); - } - return 0; - } - if (FSTART(file,fs)==0){ - printf ("%s\n Start does point to root directory. Deleting dir. \n", - path_name(file)); - MODIFY(file,name[0],DELETED_FLAG); - return 0; - } - } - if (FSTART(file,fs) >= fs->clusters+2) { - printf("%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n", - path_name(file),FSTART(file,fs),fs->clusters+1); - if (!file->offset) - die( "Bad FAT32 root directory! (bad start cluster)\n" ); - MODIFY_START(file,0,fs); - } - clusters = prev = 0; - for (curr = FSTART(file,fs) ? FSTART(file,fs) : - -1; curr != -1; curr = next_cluster(fs,curr)) { - if (!fs->fat[curr].value || bad_cluster(fs,curr)) { - printf("%s\n Contains a %s cluster (%lu). Assuming EOF.\n", - path_name(file),fs->fat[curr].value ? "bad" : "free",curr); - if (prev) set_fat(fs,prev,-1); - else if (!file->offset) - die( "FAT32 root dir starts with a bad cluster!" ); - else MODIFY_START(file,0,fs); - break; - } - if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) <= - clusters*fs->cluster_size) { - printf("%s\n File size is %u bytes, cluster chain length is > %lu " - "bytes.\n Truncating file to %u bytes.\n",path_name(file), - CF_LE_L(file->dir_ent.size),clusters*fs->cluster_size, - CF_LE_L(file->dir_ent.size)); - truncate_file(fs,file,clusters); - break; - } - if ((owner = get_owner(fs,curr))) { - int do_trunc = 0; - printf("%s and\n",path_name(owner)); - printf("%s\n share clusters.\n",path_name(file)); - clusters2 = 0; - for (walk = FSTART(owner,fs); walk > 0 && walk != -1; walk = - next_cluster(fs,walk)) - if (walk == curr) break; - else clusters2++; - restart = file->dir_ent.attr & ATTR_DIR; - if (!owner->offset) { - printf( " Truncating second to %lu bytes because first " - "is FAT32 root dir.\n", clusters2*fs->cluster_size ); - do_trunc = 2; - } - else if (!file->offset) { - printf( " Truncating first to %lu bytes because second " - "is FAT32 root dir.\n", clusters*fs->cluster_size ); - do_trunc = 1; - } - else if (interactive) - printf("1) Truncate first to %lu bytes%s\n" - "2) Truncate second to %lu bytes\n",clusters*fs->cluster_size, - restart ? " and restart" : "",clusters2*fs->cluster_size); - else printf(" Truncating second to %lu bytes.\n",clusters2* - fs->cluster_size); - if (do_trunc != 2 && - (do_trunc == 1 || - (interactive && get_key("12","?") == '1'))) { - prev = 0; - clusters = 0; - for (this = FSTART(owner,fs); this > 0 && this != -1; this = - next_cluster(fs,this)) { - if (this == curr) { - if (prev) set_fat(fs,prev,-1); - else MODIFY_START(owner,0,fs); - MODIFY(owner,size,CT_LE_L(clusters*fs->cluster_size)); - if (restart) return 1; - while (this > 0 && this != -1) { - set_owner(fs,this,NULL); - this = next_cluster(fs,this); - } - break; - } - clusters++; - prev = this; - } - if (this != curr) - die("Internal error: didn't find cluster %d in chain" - " starting at %d",curr,FSTART(owner,fs)); - } - else { - if (prev) set_fat(fs,prev,-1); - else MODIFY_START(file,0,fs); - break; - } - } - set_owner(fs,curr,file); - clusters++; - prev = curr; - } - if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) > - clusters*fs->cluster_size) { - printf("%s\n File size is %u bytes, cluster chain length is %lu bytes." - "\n Truncating file to %lu bytes.\n",path_name(file),CF_LE_L(file-> - dir_ent.size),clusters*fs->cluster_size,clusters*fs->cluster_size); - MODIFY(file,size,CT_LE_L(clusters*fs->cluster_size)); - } - return 0; -} - - -static int check_files(DOS_FS *fs,DOS_FILE *start) -{ - while (start) { - if (check_file(fs,start)) return 1; - start = start->next; - } - return 0; -} - - -static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots) -{ - DOS_FILE *parent,**walk,**scan; - int dot,dotdot,skip,redo; - int good,bad; - - if (!*root) return 0; - parent = (*root)->parent; - good = bad = 0; - for (walk = root; *walk; walk = &(*walk)->next) - if (bad_name((*walk)->dir_ent.name)) bad++; - else good++; - if (*root && parent && good+bad > 4 && bad > good/2) { - printf("%s\n Has a large number of bad entries. (%d/%d)\n", - path_name(parent),bad,good+bad); - if (!dots) printf( " Not dropping root directory.\n" ); - else if (!interactive) printf(" Not dropping it in auto-mode.\n"); - else if (get_key("yn","Drop directory ? (y/n)") == 'y') { - truncate_file(fs,parent,0); - MODIFY(parent,name[0],DELETED_FLAG); - /* buglet: deleted directory stays in the list. */ - return 1; - } - } - dot = dotdot = redo = 0; - walk = root; - while (*walk) { - if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME) || - !strncmp((*walk)->dir_ent.name,MSDOS_DOTDOT,MSDOS_NAME)) { - if (handle_dot(fs,*walk,dots)) { - *walk = (*walk)->next; - continue; - } - if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) dot++; - else dotdot++; - } - if (!((*walk)->dir_ent.attr & ATTR_VOLUME) && - bad_name((*walk)->dir_ent.name)) { - printf("%s\n Bad file name.\n",path_name(*walk)); - if (interactive) - printf("1) Drop file\n2) Rename file\n3) Auto-rename\n" - "4) Keep it\n"); - else printf(" Auto-renaming it.\n"); - switch (interactive ? get_key("1234","?") : '3') { - case '1': - drop_file(fs,*walk); - walk = &(*walk)->next; - continue; - case '2': - rename_file(*walk); - redo = 1; - break; - case '3': - auto_rename(*walk); - printf(" Renamed to %s\n",file_name((*walk)->dir_ent. - name)); - break; - case '4': - break; - } - } - /* don't check for duplicates of the volume label */ - if (!((*walk)->dir_ent.attr & ATTR_VOLUME)) { - scan = &(*walk)->next; - skip = 0; - while (*scan && !skip) { - if (!((*scan)->dir_ent.attr & ATTR_VOLUME) && - !strncmp((*walk)->dir_ent.name,(*scan)->dir_ent.name,MSDOS_NAME)) { - printf("%s\n Duplicate directory entry.\n First %s\n", - path_name(*walk),file_stat(*walk)); - printf(" Second %s\n",file_stat(*scan)); - if (interactive) - printf("1) Drop first\n2) Drop second\n3) Rename first\n" - "4) Rename second\n5) Auto-rename first\n" - "6) Auto-rename second\n"); - else printf(" Auto-renaming second.\n"); - switch (interactive ? get_key("123456","?") : '6') { - case '1': - drop_file(fs,*walk); - *walk = (*walk)->next; - skip = 1; - break; - case '2': - drop_file(fs,*scan); - *scan = (*scan)->next; - continue; - case '3': - rename_file(*walk); - printf(" Renamed to %s\n",path_name(*walk)); - redo = 1; - break; - case '4': - rename_file(*scan); - printf(" Renamed to %s\n",path_name(*walk)); - redo = 1; - break; - case '5': - auto_rename(*walk); - printf(" Renamed to %s\n",file_name((*walk)->dir_ent. - name)); - break; - case '6': - auto_rename(*scan); - printf(" Renamed to %s\n",file_name((*scan)->dir_ent. - name)); - break; - } - } - scan = &(*scan)->next; - } - if (skip) continue; - } - if (!redo) walk = &(*walk)->next; - else { - walk = root; - dot = dotdot = redo = 0; - } - } - if (dots && !dot) - printf("%s\n \".\" is missing. Can't fix this yet.\n", - path_name(parent)); - if (dots && !dotdot) - printf("%s\n \"..\" is missing. Can't fix this yet.\n", - path_name(parent)); - return 0; -} - - -static void test_file(DOS_FS *fs,DOS_FILE *file,int read_test) -{ - DOS_FILE *owner; - unsigned long walk,prev,clusters,next_clu; - - prev = clusters = 0; - for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2; - walk = next_clu) { - next_clu = next_cluster(fs,walk); - if ((owner = get_owner(fs,walk))) { - if (owner == file) { - printf("%s\n Circular cluster chain. Truncating to %lu " - "cluster%s.\n",path_name(file),clusters,clusters == 1 ? "" : - "s"); - if (prev) set_fat(fs,prev,-1); - else if (!file->offset) - die( "Bad FAT32 root directory! (bad start cluster)\n" ); - else MODIFY_START(file,0,fs); - } - break; - } - if (bad_cluster(fs,walk)) break; - if (read_test) { - if (fs_test(cluster_start(fs,walk),fs->cluster_size)) { - prev = walk; - clusters++; - } - else { - printf("%s\n Cluster %lu (%lu) is unreadable. Skipping it.\n", - path_name(file),clusters,walk); - if (prev) set_fat(fs,prev,next_cluster(fs,walk)); - else MODIFY_START(file,next_cluster(fs,walk),fs); - set_fat(fs,walk,-2); - } - } - set_owner(fs,walk,file); - } - for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2; - walk = next_cluster(fs,walk)) - if (bad_cluster(fs,walk)) break; - else if (get_owner(fs,walk) == file) set_owner(fs,walk,NULL); - else break; -} - - -static void undelete(DOS_FS *fs,DOS_FILE *file) -{ - unsigned long clusters,left,prev,walk; - - clusters = left = (CF_LE_L(file->dir_ent.size)+fs->cluster_size-1)/ - fs->cluster_size; - prev = 0; - for (walk = FSTART(file,fs); left && walk >= 2 && walk < - fs->clusters+2 && !fs->fat[walk].value; walk++) { - left--; - if (prev) set_fat(fs,prev,walk); - prev = walk; - } - if (prev) set_fat(fs,prev,-1); - else MODIFY_START(file,0,fs); - if (left) - printf("Warning: Did only undelete %lu of %lu cluster%s.\n",clusters-left, - clusters,clusters == 1 ? "" : "s"); - -} - - -static void new_dir( void ) -{ - lfn_reset(); -} - - -static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent, - loff_t offset,FDSC **cp) -{ - DOS_FILE *new; - DIR_ENT de; - FD_TYPE type; - - char tmpBuffer[512]; // TMN: - - if (offset) { -// fs_read(offset,sizeof(DIR_ENT),&de); - fs_read(offset,sizeof(tmpBuffer),&tmpBuffer); // TMN: - memcpy(&de, tmpBuffer, sizeof(DIR_ENT)); // TMN: - } else { - memcpy(de.name," ",MSDOS_NAME); - de.attr = ATTR_DIR; - de.size = de.time = de.date = 0; - de.start = CT_LE_W(fs->root_cluster & 0xffff); - de.starthi = CT_LE_W((fs->root_cluster >> 16) & 0xffff); - } - if ((type = file_type(cp,de.name)) != fdt_none) { - if (type == fdt_undelete && (de.attr & ATTR_DIR)) - die("Can't undelete directories."); - file_modify(cp,de.name); - fs_write(offset,1,&de); - } - if (IS_FREE(de.name)) { - lfn_check_orphaned(); - return; - } - if (de.attr == VFAT_LN_ATTR) { - lfn_add_slot(&de,offset); - return; - } - new = qalloc(&mem_queue,sizeof(DOS_FILE)); - new->lfn = lfn_get(&de); - new->offset = offset; - memcpy(&new->dir_ent,&de,sizeof(de)); - new->next = new->first = NULL; - new->parent = parent; - if (type == fdt_undelete) undelete(fs,new); - **chain = new; - *chain = &new->next; - if (list) { - printf("Checking file %s",path_name(new)); - if (new->lfn) - printf(" (%s)", file_name(new->dir_ent.name) ); - printf("\n"); - } - if (offset && - strncmp(de.name,MSDOS_DOT,MSDOS_NAME) != 0 && - strncmp(de.name,MSDOS_DOTDOT,MSDOS_NAME) != 0) - ++n_files; - test_file(fs,new,test); -} - - -static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp); - - -static int scan_dir(DOS_FS *fs,DOS_FILE *this,FDSC **cp) -{ - DOS_FILE **chain; - int i; - unsigned long clu_num; - - chain = &this->first; - i = 0; - clu_num = FSTART(this,fs); - new_dir(); - while (clu_num > 0 && clu_num != -1) { - add_file(fs,&chain,this,cluster_start(fs,clu_num)+(i % fs-> - cluster_size),cp); - i += sizeof(DIR_ENT); - if (!(i % fs->cluster_size)) - if ((clu_num = next_cluster(fs,clu_num)) == 0 || clu_num == -1) - break; - } - lfn_check_orphaned(); - if (check_dir(fs,&this->first,this->offset)) return 0; - if (check_files(fs,this->first)) return 1; - return subdirs(fs,this,cp); -} - - -static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp) -{ - DOS_FILE *walk; - - for (walk = parent ? parent->first : root; walk; walk = walk->next) - if (walk->dir_ent.attr & ATTR_DIR) - if (strncmp(walk->dir_ent.name,MSDOS_DOT,MSDOS_NAME) && - strncmp(walk->dir_ent.name,MSDOS_DOTDOT,MSDOS_NAME)) - if (scan_dir(fs,walk,file_cd(cp,walk->dir_ent.name))) return 1; - return 0; -} - - -int scan_root(DOS_FS *fs) -{ - DOS_FILE **chain; - int i; - - root = NULL; - chain = &root; - new_dir(); - if (fs->root_cluster) { - add_file(fs,&chain,NULL,0,&fp_root); - } - else { - for (i = 0; i < fs->root_entries; i++) - add_file(fs,&chain,NULL,fs->root_start+i*sizeof(DIR_ENT),&fp_root); - } - lfn_check_orphaned(); - (void) check_dir(fs,&root,0); - if (check_files(fs,root)) return 1; - return subdirs(fs,NULL,&fp_root); -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +/* check.c - Check and repair a PC/MS-DOS file system */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "dosfsck.h" +#include "io.h" +#include "fat.h" +#include "file.h" +#include "lfn.h" +#include "check.h" + + +static DOS_FILE *root; + +/* get start field of a dir entry */ +#define FSTART(p,fs) \ + ((unsigned long)CF_LE_W(p->dir_ent.start) | \ + (fs->fat_bits == 32 ? CF_LE_W(p->dir_ent.starthi) << 16 : 0)) + +#define MODIFY(p,i,v) \ + do { \ + if (p->offset) { \ + p->dir_ent.i = v; \ + fs_write(p->offset+offsetof(DIR_ENT,i), \ + sizeof(p->dir_ent.i),&p->dir_ent.i); \ + } \ + } while(0) + +#define MODIFY_START(p,v,fs) \ + do { \ + unsigned long __v = (v); \ + if (!p->offset) { \ + /* writing to fake entry for FAT32 root dir */ \ + if (!__v) die("Oops, deleting FAT32 root dir!"); \ + fs->root_cluster = __v; \ + p->dir_ent.start = CT_LE_W(__v&0xffff); \ + p->dir_ent.starthi = CT_LE_W(__v>>16); \ + __v = CT_LE_L(__v); \ + fs_write((loff_t)offsetof(struct boot_sector,root_cluster), \ + sizeof(((struct boot_sector *)0)->root_cluster), \ + &__v); \ + } \ + else { \ + MODIFY(p,start,CT_LE_W((__v)&0xffff)); \ + if (fs->fat_bits == 32) \ + MODIFY(p,starthi,CT_LE_W((__v)>>16)); \ + } \ + } while(0) + + +loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern) +{ + static int curr_num = 0; + loff_t offset; + + if (fs->root_cluster) { + DIR_ENT d2; + int i = 0, got = 0; + unsigned long clu_num, prev = 0; + loff_t offset2; + + clu_num = fs->root_cluster; + offset = cluster_start(fs,clu_num); + while (clu_num > 0 && clu_num != -1) { + fs_read(offset,sizeof(DIR_ENT),&d2); + if (IS_FREE(d2.name) && d2.attr != VFAT_LN_ATTR) { + got = 1; + break; + } + i += sizeof(DIR_ENT); + offset += sizeof(DIR_ENT); + if ((i % fs->cluster_size) == 0) { + prev = clu_num; + if ((clu_num = next_cluster(fs,clu_num)) == 0 || clu_num == -1) + break; + offset = cluster_start(fs,clu_num); + } + } + if (!got) { + /* no free slot, need to extend root dir: alloc next free cluster + * after previous one */ + if (!prev) + die("Root directory has no cluster allocated!"); + for (clu_num = prev+1; clu_num != prev; clu_num++) { + if (clu_num >= fs->clusters+2) clu_num = 2; + if (!fs->fat[clu_num].value) + break; + } + if (clu_num == prev) + die("Root directory full and no free cluster"); + set_fat(fs,prev,clu_num); + set_fat(fs,clu_num,-1); + set_owner(fs, clu_num, get_owner(fs, fs->root_cluster)); + /* clear new cluster */ + memset( &d2, 0, sizeof(d2) ); + offset = cluster_start(fs,clu_num); + for( i = 0; i < (int)fs->cluster_size; i += sizeof(DIR_ENT) ) + fs_write( offset+i, sizeof(d2), &d2 ); + } + memset(de,0,sizeof(DIR_ENT)); + while (1) { + sprintf(de->name,pattern,curr_num); + clu_num = fs->root_cluster; + i = 0; + offset2 = cluster_start(fs,clu_num); + while (clu_num > 0 && clu_num != -1) { + fs_read(offset2,sizeof(DIR_ENT),&d2); + if (offset2 != offset && + !strncmp(d2.name,de->name,MSDOS_NAME)) + break; + i += sizeof(DIR_ENT); + offset2 += sizeof(DIR_ENT); + if ((i % fs->cluster_size) == 0) { + if ((clu_num = next_cluster(fs,clu_num)) == 0 || + clu_num == -1) + break; + offset2 = cluster_start(fs,clu_num); + } + } + if (clu_num == 0 || clu_num == -1) + break; + if (++curr_num >= 10000) die("Unable to create unique name"); + } + } + else { + DIR_ENT *root; + int next_free = 0, scan; + + root = alloc(fs->root_entries*sizeof(DIR_ENT)); + fs_read(fs->root_start,fs->root_entries*sizeof(DIR_ENT),root); + + while (next_free < (int)fs->root_entries) + if (IS_FREE(root[next_free].name) && + root[next_free].attr != VFAT_LN_ATTR) + break; + else next_free++; + if (next_free == (int)fs->root_entries) + die("Root directory is full."); + offset = fs->root_start+next_free*sizeof(DIR_ENT); + memset(de,0,sizeof(DIR_ENT)); + while (1) { + sprintf(de->name,pattern,curr_num); + for (scan = 0; scan < (int)fs->root_entries; scan++) + if (scan != next_free && + !strncmp(root[scan].name,de->name,MSDOS_NAME)) + break; + if (scan == (int)fs->root_entries) break; + if (++curr_num >= 10000) die("Unable to create unique name"); + } + free(root); + } + ++n_files; + return offset; +} + + +static char *path_name(DOS_FILE *file) +{ +// static char path[PATH_MAX*2]; + static char path[MAX_PATH*2]; + + if (!file) *path = 0; + else { + if (strlen(path_name(file->parent)) > MAX_PATH) + die("Path name too long."); + if (strcmp(path,"/") != 0) strcat(path,"/"); + strcpy(strrchr(path,0),file->lfn?file->lfn:file_name(file->dir_ent.name)); + } + return path; +} + + +static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; + /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */ + + +/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ + +time_t date_dos2unix(unsigned short time,unsigned short date) +{ + int month,year; + time_t secs; + + month = ((date >> 5) & 15)-1; + year = date >> 9; + secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* + ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && + month < 2 ? 1 : 0)+3653); + /* days since 1.1.70 plus 80's leap day */ + return secs; +} + + +static char *file_stat(DOS_FILE *file) +{ + static char temp[100]; + struct tm *tm; + char tmp[100]; + time_t date; + + date = date_dos2unix(CF_LE_W(file->dir_ent.time),CF_LE_W(file-> + dir_ent.date)); + tm = localtime(&date); + strftime(tmp,99,"%H:%M:%S %b %d %Y",tm); + sprintf(temp," Size %u bytes, date %s",CF_LE_L(file->dir_ent.size),tmp); + return temp; +} + + +static int bad_name(unsigned char *name) +{ + int i, spc, suspicious = 0; + char *bad_chars = atari_format ? "*?\\/:" : "*?<>|\"\\/:"; + + /* Do not complain about (and auto-correct) the extended attribute files + * of OS/2. */ + if (strncmp(name,"EA DATA SF",11) == 0 || + strncmp(name,"WP ROOT SF",11) == 0) return 0; + + for (i = 0; i < 8; i++) { + if (name[i] < ' ' || name[i] == 0x7f) return 1; + if (name[i] > 0x7f) ++suspicious; + if (strchr(bad_chars,name[i])) return 1; + } + + for (i = 8; i < 11; i++) { + if (name[i] < ' ' || name[i] == 0x7f) return 1; + if (name[i] > 0x7f) ++suspicious; + if (strchr(bad_chars,name[i])) return 1; + } + + spc = 0; + for (i = 0; i < 8; i++) { + if (name[i] == ' ') + spc = 1; + else if (spc) + /* non-space after a space not allowed, space terminates the name + * part */ + return 1; + } + + spc = 0; + for (i = 8; i < 11; i++) { + if (name[i] == ' ') + spc = 1; + else if (spc) + /* non-space after a space not allowed, space terminates the name + * part */ + return 1; + } + + /* Under GEMDOS, chars >= 128 are never allowed. */ + if (atari_format && suspicious) + return 1; + + /* Only complain about too much suspicious chars in interactive mode, + * never correct them automatically. The chars are all basically ok, so we + * shouldn't auto-correct such names. */ + if (interactive && suspicious > 6) + return 1; + return 0; +} + + +static void drop_file(DOS_FS *fs,DOS_FILE *file) +{ + unsigned long cluster; + + MODIFY(file,name[0],DELETED_FLAG); + for (cluster = FSTART(file,fs); cluster > 0 && cluster < + fs->clusters+2; cluster = next_cluster(fs,cluster)) + set_owner(fs,cluster,NULL); + --n_files; +} + + +static void truncate_file(DOS_FS *fs,DOS_FILE *file,unsigned long clusters) +{ + int deleting; + unsigned long walk,next,prev; + + walk = FSTART(file,fs); + prev = 0; + if ((deleting = !clusters)) MODIFY_START(file,0,fs); + while (walk > 0 && walk != -1) { + next = next_cluster(fs,walk); + if (deleting) set_fat(fs,walk,0); + else if ((deleting = !--clusters)) set_fat(fs,walk,-1); + prev = walk; + walk = next; + } +} + + +static void auto_rename(DOS_FILE *file) +{ + DOS_FILE *first,*walk; + int number; + + if (!file->offset) return; /* cannot rename FAT32 root dir */ + first = file->parent ? file->parent->first : root; + number = 0; + while (1) { + sprintf(file->dir_ent.name,"FSCK%04d",number); + strncpy(file->dir_ent.ext,"REN",3); + for (walk = first; walk; walk = walk->next) + if (walk != file && !strncmp(walk->dir_ent.name,file->dir_ent. + name,MSDOS_NAME)) break; + if (!walk) { + fs_write(file->offset,MSDOS_NAME,file->dir_ent.name); + return; + } + number++; + } + die("Can't generate a unique name."); +} + + +static void rename_file(DOS_FILE *file) +{ + unsigned char name[46]; + unsigned char *walk,*here; + + if (!file->offset) { + printf( "Cannot rename FAT32 root dir\n" ); + return; /* cannot rename FAT32 root dir */ + } + while (1) { + printf("New name: "); + fflush(stdout); + if (fgets(name,45,stdin)) { + if ((here = strchr(name,'\n'))) *here = 0; + for (walk = strrchr(name,0); walk >= name && (*walk == ' ' || + *walk == '\t'); walk--); + walk[1] = 0; + for (walk = name; *walk == ' ' || *walk == '\t'; walk++); + if (file_cvt(walk,file->dir_ent.name)) { + fs_write(file->offset,MSDOS_NAME,file->dir_ent.name); + return; + } + } + } +} + + +static int handle_dot(DOS_FS *fs,DOS_FILE *file,int dots) +{ + char *name; + + name = strncmp(file->dir_ent.name,MSDOS_DOT,MSDOS_NAME) ? ".." : "."; + if (!(file->dir_ent.attr & ATTR_DIR)) { + printf("%s\n Is a non-directory.\n",path_name(file)); + if (interactive) + printf("1) Drop it\n2) Auto-rename\n3) Rename\n" + "4) Convert to directory\n"); + else printf(" Auto-renaming it.\n"); + switch (interactive ? get_key("1234","?") : '2') { + case '1': + drop_file(fs,file); + return 1; + case '2': + auto_rename(file); + printf(" Renamed to %s\n",file_name(file->dir_ent.name)); + return 0; + case '3': + rename_file(file); + return 0; + case '4': + MODIFY(file,size,CT_LE_L(0)); + MODIFY(file,attr,file->dir_ent.attr | ATTR_DIR); + break; + } + } + if (!dots) { + printf("Root contains directory \"%s\". Dropping it.\n",name); + drop_file(fs,file); + return 1; + } + return 0; +} + + +static int check_file(DOS_FS *fs,DOS_FILE *file) +{ + DOS_FILE *owner; + int restart; + unsigned long expect,curr,this,clusters,prev,walk,clusters2; + + if (file->dir_ent.attr & ATTR_DIR) { + if (CF_LE_L(file->dir_ent.size)) { + printf("%s\n Directory has non-zero size. Fixing it.\n", + path_name(file)); + MODIFY(file,size,CT_LE_L(0)); + } + if (file->parent && !strncmp(file->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) { + expect = FSTART(file->parent,fs); + if (FSTART(file,fs) != expect) { + printf("%s\n Start (%ld) does not point to parent (%ld)\n", + path_name(file),FSTART(file,fs),expect); + MODIFY_START(file,expect,fs); + } + return 0; + } + if (file->parent && !strncmp(file->dir_ent.name,MSDOS_DOTDOT, + MSDOS_NAME)) { + expect = file->parent->parent ? FSTART(file->parent->parent,fs):0; + if (fs->root_cluster && expect == fs->root_cluster) + expect = 0; + if (FSTART(file,fs) != expect) { + printf("%s\n Start (%lu) does not point to .. (%lu)\n", + path_name(file),FSTART(file,fs),expect); + MODIFY_START(file,expect,fs); + } + return 0; + } + if (FSTART(file,fs)==0){ + printf ("%s\n Start does point to root directory. Deleting dir. \n", + path_name(file)); + MODIFY(file,name[0],DELETED_FLAG); + return 0; + } + } + if (FSTART(file,fs) >= fs->clusters+2) { + printf("%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n", + path_name(file),FSTART(file,fs),fs->clusters+1); + if (!file->offset) + die( "Bad FAT32 root directory! (bad start cluster)\n" ); + MODIFY_START(file,0,fs); + } + clusters = prev = 0; + for (curr = FSTART(file,fs) ? FSTART(file,fs) : + -1; curr != -1; curr = next_cluster(fs,curr)) { + if (!fs->fat[curr].value || bad_cluster(fs,curr)) { + printf("%s\n Contains a %s cluster (%lu). Assuming EOF.\n", + path_name(file),fs->fat[curr].value ? "bad" : "free",curr); + if (prev) set_fat(fs,prev,-1); + else if (!file->offset) + die( "FAT32 root dir starts with a bad cluster!" ); + else MODIFY_START(file,0,fs); + break; + } + if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) <= + clusters*fs->cluster_size) { + printf("%s\n File size is %u bytes, cluster chain length is > %lu " + "bytes.\n Truncating file to %u bytes.\n",path_name(file), + CF_LE_L(file->dir_ent.size),clusters*fs->cluster_size, + CF_LE_L(file->dir_ent.size)); + truncate_file(fs,file,clusters); + break; + } + if ((owner = get_owner(fs,curr))) { + int do_trunc = 0; + printf("%s and\n",path_name(owner)); + printf("%s\n share clusters.\n",path_name(file)); + clusters2 = 0; + for (walk = FSTART(owner,fs); walk > 0 && walk != -1; walk = + next_cluster(fs,walk)) + if (walk == curr) break; + else clusters2++; + restart = file->dir_ent.attr & ATTR_DIR; + if (!owner->offset) { + printf( " Truncating second to %lu bytes because first " + "is FAT32 root dir.\n", clusters2*fs->cluster_size ); + do_trunc = 2; + } + else if (!file->offset) { + printf( " Truncating first to %lu bytes because second " + "is FAT32 root dir.\n", clusters*fs->cluster_size ); + do_trunc = 1; + } + else if (interactive) + printf("1) Truncate first to %lu bytes%s\n" + "2) Truncate second to %lu bytes\n",clusters*fs->cluster_size, + restart ? " and restart" : "",clusters2*fs->cluster_size); + else printf(" Truncating second to %lu bytes.\n",clusters2* + fs->cluster_size); + if (do_trunc != 2 && + (do_trunc == 1 || + (interactive && get_key("12","?") == '1'))) { + prev = 0; + clusters = 0; + for (this = FSTART(owner,fs); this > 0 && this != -1; this = + next_cluster(fs,this)) { + if (this == curr) { + if (prev) set_fat(fs,prev,-1); + else MODIFY_START(owner,0,fs); + MODIFY(owner,size,CT_LE_L(clusters*fs->cluster_size)); + if (restart) return 1; + while (this > 0 && this != -1) { + set_owner(fs,this,NULL); + this = next_cluster(fs,this); + } + break; + } + clusters++; + prev = this; + } + if (this != curr) + die("Internal error: didn't find cluster %d in chain" + " starting at %d",curr,FSTART(owner,fs)); + } + else { + if (prev) set_fat(fs,prev,-1); + else MODIFY_START(file,0,fs); + break; + } + } + set_owner(fs,curr,file); + clusters++; + prev = curr; + } + if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) > + clusters*fs->cluster_size) { + printf("%s\n File size is %u bytes, cluster chain length is %lu bytes." + "\n Truncating file to %lu bytes.\n",path_name(file),CF_LE_L(file-> + dir_ent.size),clusters*fs->cluster_size,clusters*fs->cluster_size); + MODIFY(file,size,CT_LE_L(clusters*fs->cluster_size)); + } + return 0; +} + + +static int check_files(DOS_FS *fs,DOS_FILE *start) +{ + while (start) { + if (check_file(fs,start)) return 1; + start = start->next; + } + return 0; +} + + +static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots) +{ + DOS_FILE *parent,**walk,**scan; + int dot,dotdot,skip,redo; + int good,bad; + + if (!*root) return 0; + parent = (*root)->parent; + good = bad = 0; + for (walk = root; *walk; walk = &(*walk)->next) + if (bad_name((*walk)->dir_ent.name)) bad++; + else good++; + if (*root && parent && good+bad > 4 && bad > good/2) { + printf("%s\n Has a large number of bad entries. (%d/%d)\n", + path_name(parent),bad,good+bad); + if (!dots) printf( " Not dropping root directory.\n" ); + else if (!interactive) printf(" Not dropping it in auto-mode.\n"); + else if (get_key("yn","Drop directory ? (y/n)") == 'y') { + truncate_file(fs,parent,0); + MODIFY(parent,name[0],DELETED_FLAG); + /* buglet: deleted directory stays in the list. */ + return 1; + } + } + dot = dotdot = redo = 0; + walk = root; + while (*walk) { + if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME) || + !strncmp((*walk)->dir_ent.name,MSDOS_DOTDOT,MSDOS_NAME)) { + if (handle_dot(fs,*walk,dots)) { + *walk = (*walk)->next; + continue; + } + if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) dot++; + else dotdot++; + } + if (!((*walk)->dir_ent.attr & ATTR_VOLUME) && + bad_name((*walk)->dir_ent.name)) { + printf("%s\n Bad file name.\n",path_name(*walk)); + if (interactive) + printf("1) Drop file\n2) Rename file\n3) Auto-rename\n" + "4) Keep it\n"); + else printf(" Auto-renaming it.\n"); + switch (interactive ? get_key("1234","?") : '3') { + case '1': + drop_file(fs,*walk); + walk = &(*walk)->next; + continue; + case '2': + rename_file(*walk); + redo = 1; + break; + case '3': + auto_rename(*walk); + printf(" Renamed to %s\n",file_name((*walk)->dir_ent. + name)); + break; + case '4': + break; + } + } + /* don't check for duplicates of the volume label */ + if (!((*walk)->dir_ent.attr & ATTR_VOLUME)) { + scan = &(*walk)->next; + skip = 0; + while (*scan && !skip) { + if (!((*scan)->dir_ent.attr & ATTR_VOLUME) && + !strncmp((*walk)->dir_ent.name,(*scan)->dir_ent.name,MSDOS_NAME)) { + printf("%s\n Duplicate directory entry.\n First %s\n", + path_name(*walk),file_stat(*walk)); + printf(" Second %s\n",file_stat(*scan)); + if (interactive) + printf("1) Drop first\n2) Drop second\n3) Rename first\n" + "4) Rename second\n5) Auto-rename first\n" + "6) Auto-rename second\n"); + else printf(" Auto-renaming second.\n"); + switch (interactive ? get_key("123456","?") : '6') { + case '1': + drop_file(fs,*walk); + *walk = (*walk)->next; + skip = 1; + break; + case '2': + drop_file(fs,*scan); + *scan = (*scan)->next; + continue; + case '3': + rename_file(*walk); + printf(" Renamed to %s\n",path_name(*walk)); + redo = 1; + break; + case '4': + rename_file(*scan); + printf(" Renamed to %s\n",path_name(*walk)); + redo = 1; + break; + case '5': + auto_rename(*walk); + printf(" Renamed to %s\n",file_name((*walk)->dir_ent. + name)); + break; + case '6': + auto_rename(*scan); + printf(" Renamed to %s\n",file_name((*scan)->dir_ent. + name)); + break; + } + } + scan = &(*scan)->next; + } + if (skip) continue; + } + if (!redo) walk = &(*walk)->next; + else { + walk = root; + dot = dotdot = redo = 0; + } + } + if (dots && !dot) + printf("%s\n \".\" is missing. Can't fix this yet.\n", + path_name(parent)); + if (dots && !dotdot) + printf("%s\n \"..\" is missing. Can't fix this yet.\n", + path_name(parent)); + return 0; +} + + +static void test_file(DOS_FS *fs,DOS_FILE *file,int read_test) +{ + DOS_FILE *owner; + unsigned long walk,prev,clusters,next_clu; + + prev = clusters = 0; + for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2; + walk = next_clu) { + next_clu = next_cluster(fs,walk); + if ((owner = get_owner(fs,walk))) { + if (owner == file) { + printf("%s\n Circular cluster chain. Truncating to %lu " + "cluster%s.\n",path_name(file),clusters,clusters == 1 ? "" : + "s"); + if (prev) set_fat(fs,prev,-1); + else if (!file->offset) + die( "Bad FAT32 root directory! (bad start cluster)\n" ); + else MODIFY_START(file,0,fs); + } + break; + } + if (bad_cluster(fs,walk)) break; + if (read_test) { + if (fs_test(cluster_start(fs,walk),fs->cluster_size)) { + prev = walk; + clusters++; + } + else { + printf("%s\n Cluster %lu (%lu) is unreadable. Skipping it.\n", + path_name(file),clusters,walk); + if (prev) set_fat(fs,prev,next_cluster(fs,walk)); + else MODIFY_START(file,next_cluster(fs,walk),fs); + set_fat(fs,walk,-2); + } + } + set_owner(fs,walk,file); + } + for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2; + walk = next_cluster(fs,walk)) + if (bad_cluster(fs,walk)) break; + else if (get_owner(fs,walk) == file) set_owner(fs,walk,NULL); + else break; +} + + +static void undelete(DOS_FS *fs,DOS_FILE *file) +{ + unsigned long clusters,left,prev,walk; + + clusters = left = (CF_LE_L(file->dir_ent.size)+fs->cluster_size-1)/ + fs->cluster_size; + prev = 0; + for (walk = FSTART(file,fs); left && walk >= 2 && walk < + fs->clusters+2 && !fs->fat[walk].value; walk++) { + left--; + if (prev) set_fat(fs,prev,walk); + prev = walk; + } + if (prev) set_fat(fs,prev,-1); + else MODIFY_START(file,0,fs); + if (left) + printf("Warning: Did only undelete %lu of %lu cluster%s.\n",clusters-left, + clusters,clusters == 1 ? "" : "s"); + +} + + +static void new_dir( void ) +{ + lfn_reset(); +} + + +static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent, + loff_t offset,FDSC **cp) +{ + DOS_FILE *new; + DIR_ENT de; + FD_TYPE type; + + char tmpBuffer[512]; // TMN: + + if (offset) { +// fs_read(offset,sizeof(DIR_ENT),&de); + fs_read(offset,sizeof(tmpBuffer),&tmpBuffer); // TMN: + memcpy(&de, tmpBuffer, sizeof(DIR_ENT)); // TMN: + } else { + memcpy(de.name," ",MSDOS_NAME); + de.attr = ATTR_DIR; + de.size = de.time = de.date = 0; + de.start = CT_LE_W(fs->root_cluster & 0xffff); + de.starthi = CT_LE_W((fs->root_cluster >> 16) & 0xffff); + } + if ((type = file_type(cp,de.name)) != fdt_none) { + if (type == fdt_undelete && (de.attr & ATTR_DIR)) + die("Can't undelete directories."); + file_modify(cp,de.name); + fs_write(offset,1,&de); + } + if (IS_FREE(de.name)) { + lfn_check_orphaned(); + return; + } + if (de.attr == VFAT_LN_ATTR) { + lfn_add_slot(&de,offset); + return; + } + new = qalloc(&mem_queue,sizeof(DOS_FILE)); + new->lfn = lfn_get(&de); + new->offset = offset; + memcpy(&new->dir_ent,&de,sizeof(de)); + new->next = new->first = NULL; + new->parent = parent; + if (type == fdt_undelete) undelete(fs,new); + **chain = new; + *chain = &new->next; + if (list) { + printf("Checking file %s",path_name(new)); + if (new->lfn) + printf(" (%s)", file_name(new->dir_ent.name) ); + printf("\n"); + } + if (offset && + strncmp(de.name,MSDOS_DOT,MSDOS_NAME) != 0 && + strncmp(de.name,MSDOS_DOTDOT,MSDOS_NAME) != 0) + ++n_files; + test_file(fs,new,test); +} + + +static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp); + + +static int scan_dir(DOS_FS *fs,DOS_FILE *this,FDSC **cp) +{ + DOS_FILE **chain; + int i; + unsigned long clu_num; + + chain = &this->first; + i = 0; + clu_num = FSTART(this,fs); + new_dir(); + while (clu_num > 0 && clu_num != -1) { + add_file(fs,&chain,this,cluster_start(fs,clu_num)+(i % fs-> + cluster_size),cp); + i += sizeof(DIR_ENT); + if (!(i % fs->cluster_size)) + if ((clu_num = next_cluster(fs,clu_num)) == 0 || clu_num == -1) + break; + } + lfn_check_orphaned(); + if (check_dir(fs,&this->first,this->offset)) return 0; + if (check_files(fs,this->first)) return 1; + return subdirs(fs,this,cp); +} + + +static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp) +{ + DOS_FILE *walk; + + for (walk = parent ? parent->first : root; walk; walk = walk->next) + if (walk->dir_ent.attr & ATTR_DIR) + if (strncmp(walk->dir_ent.name,MSDOS_DOT,MSDOS_NAME) && + strncmp(walk->dir_ent.name,MSDOS_DOTDOT,MSDOS_NAME)) + if (scan_dir(fs,walk,file_cd(cp,walk->dir_ent.name))) return 1; + return 0; +} + + +int scan_root(DOS_FS *fs) +{ + DOS_FILE **chain; + int i; + + root = NULL; + chain = &root; + new_dir(); + if (fs->root_cluster) { + add_file(fs,&chain,NULL,0,&fp_root); + } + else { + for (i = 0; i < fs->root_entries; i++) + add_file(fs,&chain,NULL,fs->root_start+i*sizeof(DIR_ENT),&fp_root); + } + lfn_check_orphaned(); + (void) check_dir(fs,&root,0); + if (check_files(fs,root)) return 1; + return subdirs(fs,NULL,&fp_root); +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/check.h b/rosapps/sysutils/dosfsck/check.h index 4498b7fac9c..38f1c686b5c 100644 --- a/rosapps/sysutils/dosfsck/check.h +++ b/rosapps/sysutils/dosfsck/check.h @@ -1,23 +1,23 @@ -/* check.h - Check and repair a PC/MS-DOS file system */ - -/* Written 1993 by Werner Almesberger */ - - -#ifndef _CHECK_H -#define _CHECK_H - -loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern); - -/* Allocate a free slot in the root directory for a new file. The file name is - constructed after 'pattern', which must include a %d type format for printf - and expand to exactly 11 characters. The name actually used is written into - the 'de' structure, the rest of *de is cleared. The offset returned is to - where in the filesystem the entry belongs. */ - -int scan_root(DOS_FS *fs); - -/* Scans the root directory and recurses into all subdirectories. See check.c - for all the details. Returns a non-zero integer if the file system has to - be checked again. */ - -#endif +/* check.h - Check and repair a PC/MS-DOS file system */ + +/* Written 1993 by Werner Almesberger */ + + +#ifndef _CHECK_H +#define _CHECK_H + +loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern); + +/* Allocate a free slot in the root directory for a new file. The file name is + constructed after 'pattern', which must include a %d type format for printf + and expand to exactly 11 characters. The name actually used is written into + the 'de' structure, the rest of *de is cleared. The offset returned is to + where in the filesystem the entry belongs. */ + +int scan_root(DOS_FS *fs); + +/* Scans the root directory and recurses into all subdirectories. See check.c + for all the details. Returns a non-zero integer if the file system has to + be checked again. */ + +#endif diff --git a/rosapps/sysutils/dosfsck/common.c b/rosapps/sysutils/dosfsck/common.c index cc002ea45a6..1a481720c14 100644 --- a/rosapps/sysutils/dosfsck/common.c +++ b/rosapps/sysutils/dosfsck/common.c @@ -1,110 +1,110 @@ -/* common.c - Common functions */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#include -#include -#include -#include -#include - -#include "common.h" - - -typedef struct _link { - void *data; - struct _link *next; -} LINK; - - -void die(char *msg,...) -{ - va_list args; - - va_start(args,msg); - vfprintf(stderr,msg,args); - va_end(args); - fprintf(stderr,"\n"); - exit(1); -} - - -void pdie(char *msg,...) -{ - va_list args; - - va_start(args,msg); - vfprintf(stderr,msg,args); - va_end(args); - fprintf(stderr,":%s\n",strerror(errno)); - exit(1); -} - - -void *alloc(int size) -{ - void *this; - - if ((this = malloc(size))) return this; - pdie("malloc"); - return NULL; /* for GCC */ -} - - -void *qalloc(void **root,int size) -{ - LINK *link; - - link = alloc(sizeof(LINK)); - link->next = *root; - *root = link; - return link->data = alloc(size); -} - - -void qfree(void **root) -{ - LINK *this; - - while (*root) { - this = (LINK *) *root; - *root = this->next; - free(this->data); - free(this); - } -} - - -#ifdef min -#undef min -#endif -int min(int a,int b) -{ - return a < b ? a : b; -} - - -char get_key(char *valid,char *prompt) -{ - int ch,okay; - - while (1) { - if (prompt) printf("%s ",prompt); - fflush(stdout); - while (ch = getchar(), ch == ' ' || ch == '\t'); - if (ch == EOF) exit(1); - if (!strchr(valid,okay = ch)) okay = 0; - while (ch = getchar(), ch != '\n' && ch != EOF); - if (ch == EOF) exit(1); - if (okay) return okay; - printf("Invalid input.\n"); - } -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +/* common.c - Common functions */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#include +#include +#include +#include +#include + +#include "common.h" + + +typedef struct _link { + void *data; + struct _link *next; +} LINK; + + +void die(char *msg,...) +{ + va_list args; + + va_start(args,msg); + vfprintf(stderr,msg,args); + va_end(args); + fprintf(stderr,"\n"); + exit(1); +} + + +void pdie(char *msg,...) +{ + va_list args; + + va_start(args,msg); + vfprintf(stderr,msg,args); + va_end(args); + fprintf(stderr,":%s\n",strerror(errno)); + exit(1); +} + + +void *alloc(int size) +{ + void *this; + + if ((this = malloc(size))) return this; + pdie("malloc"); + return NULL; /* for GCC */ +} + + +void *qalloc(void **root,int size) +{ + LINK *link; + + link = alloc(sizeof(LINK)); + link->next = *root; + *root = link; + return link->data = alloc(size); +} + + +void qfree(void **root) +{ + LINK *this; + + while (*root) { + this = (LINK *) *root; + *root = this->next; + free(this->data); + free(this); + } +} + + +#ifdef min +#undef min +#endif +int min(int a,int b) +{ + return a < b ? a : b; +} + + +char get_key(char *valid,char *prompt) +{ + int ch,okay; + + while (1) { + if (prompt) printf("%s ",prompt); + fflush(stdout); + while (ch = getchar(), ch == ' ' || ch == '\t'); + if (ch == EOF) exit(1); + if (!strchr(valid,okay = ch)) okay = 0; + while (ch = getchar(), ch != '\n' && ch != EOF); + if (ch == EOF) exit(1); + if (okay) return okay; + printf("Invalid input.\n"); + } +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/common.h b/rosapps/sysutils/dosfsck/common.h index 6e9bdceed3f..cbd335795d0 100644 --- a/rosapps/sysutils/dosfsck/common.h +++ b/rosapps/sysutils/dosfsck/common.h @@ -1,42 +1,42 @@ -/* common.h - Common functions */ - -# define MSDOS_FAT12 4084 /* maximum number of clusters in a 12 bit FAT */ - -#include "version.h" - -#ifndef _COMMON_H -#define _COMMON_H - -//void die(char *msg,...) __attribute((noreturn)); -__declspec(noreturn) void die(char *msg,...); - -/* Displays a prinf-style message and terminates the program. */ - -//void pdie(char *msg,...) __attribute((noreturn)); -__declspec(noreturn) void pdie(char *msg,...); - -/* Like die, but appends an error message according to the state of errno. */ - -void *alloc(int size); - -/* mallocs SIZE bytes and returns a pointer to the data. Terminates the program - if malloc fails. */ - -void *qalloc(void **root,int size); - -/* Like alloc, but registers the data area in a list described by ROOT. */ - -void qfree(void **root); - -/* Deallocates all qalloc'ed data areas described by ROOT. */ - -//int min(int a,int b); - -/* Returns the smaller integer value of a and b. */ - -char get_key(char *valid,char *prompt); - -/* Displays PROMPT and waits for user input. Only characters in VALID are - accepted. Terminates the program on EOF. Returns the character. */ - -#endif +/* common.h - Common functions */ + +# define MSDOS_FAT12 4084 /* maximum number of clusters in a 12 bit FAT */ + +#include "version.h" + +#ifndef _COMMON_H +#define _COMMON_H + +//void die(char *msg,...) __attribute((noreturn)); +__declspec(noreturn) void die(char *msg,...); + +/* Displays a prinf-style message and terminates the program. */ + +//void pdie(char *msg,...) __attribute((noreturn)); +__declspec(noreturn) void pdie(char *msg,...); + +/* Like die, but appends an error message according to the state of errno. */ + +void *alloc(int size); + +/* mallocs SIZE bytes and returns a pointer to the data. Terminates the program + if malloc fails. */ + +void *qalloc(void **root,int size); + +/* Like alloc, but registers the data area in a list described by ROOT. */ + +void qfree(void **root); + +/* Deallocates all qalloc'ed data areas described by ROOT. */ + +//int min(int a,int b); + +/* Returns the smaller integer value of a and b. */ + +char get_key(char *valid,char *prompt); + +/* Displays PROMPT and waits for user input. Only characters in VALID are + accepted. Terminates the program on EOF. Returns the character. */ + +#endif diff --git a/rosapps/sysutils/dosfsck/compiler.h b/rosapps/sysutils/dosfsck/compiler.h index f685e93f6e0..2d3edfe38b7 100644 --- a/rosapps/sysutils/dosfsck/compiler.h +++ b/rosapps/sysutils/dosfsck/compiler.h @@ -1,158 +1,158 @@ -#ifndef __LINUX_COMPILER_H -#define __LINUX_COMPILER_H - -#ifndef __ASSEMBLY__ - -#ifdef __CHECKER__ -# define __user __attribute__((noderef, address_space(1))) -# define __kernel /* default address space */ -# define __safe __attribute__((safe)) -# define __force __attribute__((force)) -# define __nocast __attribute__((nocast)) -# define __iomem __attribute__((noderef, address_space(2))) -# define __acquires(x) __attribute__((context(0,1))) -# define __releases(x) __attribute__((context(1,0))) -# define __acquire(x) __context__(1) -# define __release(x) __context__(-1) -# define __cond_lock(x) ((x) ? ({ __context__(1); 1; }) : 0) -extern void __chk_user_ptr(void __user *); -extern void __chk_io_ptr(void __iomem *); -#else -# define __user -# define __kernel -# define __safe -# define __force -# define __nocast -# define __iomem -# define __chk_user_ptr(x) (void)0 -# define __chk_io_ptr(x) (void)0 -//# define __builtin_warning(x, y...) (1) -# define __acquires(x) -# define __releases(x) -# define __acquire(x) (void)0 -# define __release(x) (void)0 -# define __cond_lock(x) (x) -#endif - -#ifdef __KERNEL__ - -#if __GNUC__ > 4 -#error no compiler-gcc.h file for this gcc version -#elif __GNUC__ == 4 -# include -#elif __GNUC__ == 3 -# include -#elif __GNUC__ == 2 -# include -#else -# error Sorry, your compiler is too old/not recognized. -#endif - -/* Intel compiler defines __GNUC__. So we will overwrite implementations - * coming from above header files here - */ -#ifdef __INTEL_COMPILER -# include -#endif - -/* - * Generic compiler-dependent macros required for kernel - * build go below this comment. Actual compiler/compiler version - * specific implementations come from the above header files - */ - -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) - -/* Optimization barrier */ -#ifndef barrier -# define barrier() __memory_barrier() -#endif - -#ifndef RELOC_HIDE -# define RELOC_HIDE(ptr, off) \ - ({ unsigned long __ptr; \ - __ptr = (unsigned long) (ptr); \ - (typeof(ptr)) (__ptr + (off)); }) -#endif - -#endif /* __KERNEL__ */ - -#endif /* __ASSEMBLY__ */ - -/* - * Allow us to mark functions as 'deprecated' and have gcc emit a nice - * warning for each use, in hopes of speeding the functions removal. - * Usage is: - * int __deprecated foo(void) - */ -#ifndef __deprecated -# define __deprecated /* unimplemented */ -#endif - -#ifdef MODULE -#define __deprecated_for_modules __deprecated -#else -#define __deprecated_for_modules -#endif - -#ifndef __must_check -#define __must_check -#endif - -/* - * Allow us to avoid 'defined but not used' warnings on functions and data, - * as well as force them to be emitted to the assembly file. - * - * As of gcc 3.3, static functions that are not marked with attribute((used)) - * may be elided from the assembly file. As of gcc 3.3, static data not so - * marked will not be elided, but this may change in a future gcc version. - * - * In prior versions of gcc, such functions and data would be emitted, but - * would be warned about except with attribute((unused)). - */ -#ifndef __attribute_used__ -# define __attribute_used__ /* unimplemented */ -#endif - -/* - * From the GCC manual: - * - * Many functions have no effects except the return value and their - * return value depends only on the parameters and/or global - * variables. Such a function can be subject to common subexpression - * elimination and loop optimization just as an arithmetic operator - * would be. - * [...] - */ -#ifndef __attribute_pure__ -# define __attribute_pure__ /* unimplemented */ -#endif - -/* - * From the GCC manual: - * - * Many functions do not examine any values except their arguments, - * and have no effects except the return value. Basically this is - * just slightly more strict class than the `pure' attribute above, - * since function is not allowed to read global memory. - * - * Note that a function that has pointer arguments and examines the - * data pointed to must _not_ be declared `const'. Likewise, a - * function that calls a non-`const' function usually must not be - * `const'. It does not make sense for a `const' function to return - * `void'. - */ -#ifndef __attribute_const__ -# define __attribute_const__ /* unimplemented */ -#endif - -#ifndef noinline -#define noinline -#endif - -#ifndef __always_inline -#define __always_inline inline -#endif - -#endif /* __LINUX_COMPILER_H */ +#ifndef __LINUX_COMPILER_H +#define __LINUX_COMPILER_H + +#ifndef __ASSEMBLY__ + +#ifdef __CHECKER__ +# define __user __attribute__((noderef, address_space(1))) +# define __kernel /* default address space */ +# define __safe __attribute__((safe)) +# define __force __attribute__((force)) +# define __nocast __attribute__((nocast)) +# define __iomem __attribute__((noderef, address_space(2))) +# define __acquires(x) __attribute__((context(0,1))) +# define __releases(x) __attribute__((context(1,0))) +# define __acquire(x) __context__(1) +# define __release(x) __context__(-1) +# define __cond_lock(x) ((x) ? ({ __context__(1); 1; }) : 0) +extern void __chk_user_ptr(void __user *); +extern void __chk_io_ptr(void __iomem *); +#else +# define __user +# define __kernel +# define __safe +# define __force +# define __nocast +# define __iomem +# define __chk_user_ptr(x) (void)0 +# define __chk_io_ptr(x) (void)0 +//# define __builtin_warning(x, y...) (1) +# define __acquires(x) +# define __releases(x) +# define __acquire(x) (void)0 +# define __release(x) (void)0 +# define __cond_lock(x) (x) +#endif + +#ifdef __KERNEL__ + +#if __GNUC__ > 4 +#error no compiler-gcc.h file for this gcc version +#elif __GNUC__ == 4 +# include +#elif __GNUC__ == 3 +# include +#elif __GNUC__ == 2 +# include +#else +# error Sorry, your compiler is too old/not recognized. +#endif + +/* Intel compiler defines __GNUC__. So we will overwrite implementations + * coming from above header files here + */ +#ifdef __INTEL_COMPILER +# include +#endif + +/* + * Generic compiler-dependent macros required for kernel + * build go below this comment. Actual compiler/compiler version + * specific implementations come from the above header files + */ + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +/* Optimization barrier */ +#ifndef barrier +# define barrier() __memory_barrier() +#endif + +#ifndef RELOC_HIDE +# define RELOC_HIDE(ptr, off) \ + ({ unsigned long __ptr; \ + __ptr = (unsigned long) (ptr); \ + (typeof(ptr)) (__ptr + (off)); }) +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ASSEMBLY__ */ + +/* + * Allow us to mark functions as 'deprecated' and have gcc emit a nice + * warning for each use, in hopes of speeding the functions removal. + * Usage is: + * int __deprecated foo(void) + */ +#ifndef __deprecated +# define __deprecated /* unimplemented */ +#endif + +#ifdef MODULE +#define __deprecated_for_modules __deprecated +#else +#define __deprecated_for_modules +#endif + +#ifndef __must_check +#define __must_check +#endif + +/* + * Allow us to avoid 'defined but not used' warnings on functions and data, + * as well as force them to be emitted to the assembly file. + * + * As of gcc 3.3, static functions that are not marked with attribute((used)) + * may be elided from the assembly file. As of gcc 3.3, static data not so + * marked will not be elided, but this may change in a future gcc version. + * + * In prior versions of gcc, such functions and data would be emitted, but + * would be warned about except with attribute((unused)). + */ +#ifndef __attribute_used__ +# define __attribute_used__ /* unimplemented */ +#endif + +/* + * From the GCC manual: + * + * Many functions have no effects except the return value and their + * return value depends only on the parameters and/or global + * variables. Such a function can be subject to common subexpression + * elimination and loop optimization just as an arithmetic operator + * would be. + * [...] + */ +#ifndef __attribute_pure__ +# define __attribute_pure__ /* unimplemented */ +#endif + +/* + * From the GCC manual: + * + * Many functions do not examine any values except their arguments, + * and have no effects except the return value. Basically this is + * just slightly more strict class than the `pure' attribute above, + * since function is not allowed to read global memory. + * + * Note that a function that has pointer arguments and examines the + * data pointed to must _not_ be declared `const'. Likewise, a + * function that calls a non-`const' function usually must not be + * `const'. It does not make sense for a `const' function to return + * `void'. + */ +#ifndef __attribute_const__ +# define __attribute_const__ /* unimplemented */ +#endif + +#ifndef noinline +#define noinline +#endif + +#ifndef __always_inline +#define __always_inline inline +#endif + +#endif /* __LINUX_COMPILER_H */ diff --git a/rosapps/sysutils/dosfsck/dosfsck.c b/rosapps/sysutils/dosfsck/dosfsck.c index 40461bbc3b2..2fb2b28a7d4 100644 --- a/rosapps/sysutils/dosfsck/dosfsck.c +++ b/rosapps/sysutils/dosfsck/dosfsck.c @@ -1,184 +1,184 @@ -/* dosfsck.c - User interface */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#include "version.h" - -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "dosfsck.h" -#include "io.h" -#include "boot.h" -#include "fat.h" -#include "file.h" -#include "check.h" - - -int interactive = 0,list = 0,test = 0,verbose = 0,write_immed = 0; -int atari_format = 0; -unsigned n_files = 0; -void *mem_queue = NULL; - - -static void usage(char *name) -{ - fprintf(stderr,"usage: %s [-aAflrtvVwy] [-d path -d ...] " - "[-u path -u ...]\n%15sdevice\n",name,""); - fprintf(stderr," -a automatically repair the file system\n"); - fprintf(stderr," -A toggle Atari file system format\n"); - fprintf(stderr," -d path drop that file\n"); - fprintf(stderr," -f salvage unused chains to files\n"); - fprintf(stderr," -l list path names\n"); - fprintf(stderr," -n no-op, check non-interactively without changing\n"); - fprintf(stderr," -r interactively repair the file system\n"); - fprintf(stderr," -t test for bad clusters\n"); - fprintf(stderr," -u path try to undelete that (non-directory) file\n"); - fprintf(stderr," -v verbose mode\n"); - fprintf(stderr," -V perform a verification pass\n"); - fprintf(stderr," -w write changes to disk immediately\n"); - fprintf(stderr," -y same as -a, for compat with other *fsck\n"); - exit(2); -} - - -/* - * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant - * of MS-DOS filesystem by default. - */ -static void check_atari( void ) -{ -#ifdef __mc68000__ - FILE *f; - char line[128], *p; - - if (!(f = fopen( "/proc/hardware", "r" ))) { - perror( "/proc/hardware" ); - return; - } - - while( fgets( line, sizeof(line), f ) ) { - if (strncmp( line, "Model:", 6 ) == 0) { - p = line + 6; - p += strspn( p, " \t" ); - if (strncmp( p, "Atari ", 6 ) == 0) - atari_format = 1; - break; - } - } - fclose( f ); -#endif -} - - -int main(int argc,char **argv) -{ - DOS_FS fs; - int rw,salvage_files,verify,c; - unsigned long free_clusters; - - rw = salvage_files = verify = 0; - interactive = 1; - check_atari(); - - while ((c = getopt(argc,argv,"Aad:flnrtu:vVwy")) != EOF) - switch (c) { - case 'A': /* toggle Atari format */ - atari_format = !atari_format; - break; - case 'a': - case 'y': - rw = 1; - interactive = 0; - salvage_files = 1; - break; - case 'd': - file_add(optarg,fdt_drop); - break; - case 'f': - salvage_files = 1; - break; - case 'l': - list = 1; - break; - case 'n': - rw = 0; - interactive = 0; - break; - case 'r': - rw = 1; - interactive = 1; - break; - case 't': - test = 1; - break; - case 'u': - file_add(optarg,fdt_undelete); - break; - case 'v': - verbose = 1; - printf("dosfsck " VERSION " (" VERSION_DATE ")\n"); - break; - case 'V': - verify = 1; - break; - case 'w': - write_immed = 1; - break; - default: - usage(argv[0]); - } - - if ((test || write_immed) && !rw) { - fprintf(stderr,"-t and -w require -a or -r\n"); - exit(2); - } - if (optind != argc-1) usage(argv[0]); - - printf( "dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n" ); - fs_open(argv[optind],rw); - read_boot(&fs); - if (verify) printf("Starting check/repair pass.\n"); - while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue); - if (test) fix_bad(&fs); - if (salvage_files) reclaim_file(&fs); - else reclaim_free(&fs); - free_clusters = update_free(&fs); - file_unused(); - qfree(&mem_queue); - if (verify) { - printf("Starting verification pass.\n"); - read_fat(&fs); - scan_root(&fs); - reclaim_free(&fs); - qfree(&mem_queue); - } - - if (fs_changed()) { - if (rw) { - if (interactive) - rw = get_key("yn","Perform changes ? (y/n)") == 'y'; - else printf("Performing changes.\n"); - } - else - printf("Leaving file system unchanged.\n"); - } - - printf( "%s: %u files, %lu/%lu clusters\n", argv[optind], - n_files, fs.clusters - free_clusters, fs.clusters ); - - return fs_close(rw) ? 1 : 0; -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +/* dosfsck.c - User interface */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#include "version.h" + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "dosfsck.h" +#include "io.h" +#include "boot.h" +#include "fat.h" +#include "file.h" +#include "check.h" + + +int interactive = 0,list = 0,test = 0,verbose = 0,write_immed = 0; +int atari_format = 0; +unsigned n_files = 0; +void *mem_queue = NULL; + + +static void usage(char *name) +{ + fprintf(stderr,"usage: %s [-aAflrtvVwy] [-d path -d ...] " + "[-u path -u ...]\n%15sdevice\n",name,""); + fprintf(stderr," -a automatically repair the file system\n"); + fprintf(stderr," -A toggle Atari file system format\n"); + fprintf(stderr," -d path drop that file\n"); + fprintf(stderr," -f salvage unused chains to files\n"); + fprintf(stderr," -l list path names\n"); + fprintf(stderr," -n no-op, check non-interactively without changing\n"); + fprintf(stderr," -r interactively repair the file system\n"); + fprintf(stderr," -t test for bad clusters\n"); + fprintf(stderr," -u path try to undelete that (non-directory) file\n"); + fprintf(stderr," -v verbose mode\n"); + fprintf(stderr," -V perform a verification pass\n"); + fprintf(stderr," -w write changes to disk immediately\n"); + fprintf(stderr," -y same as -a, for compat with other *fsck\n"); + exit(2); +} + + +/* + * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant + * of MS-DOS filesystem by default. + */ +static void check_atari( void ) +{ +#ifdef __mc68000__ + FILE *f; + char line[128], *p; + + if (!(f = fopen( "/proc/hardware", "r" ))) { + perror( "/proc/hardware" ); + return; + } + + while( fgets( line, sizeof(line), f ) ) { + if (strncmp( line, "Model:", 6 ) == 0) { + p = line + 6; + p += strspn( p, " \t" ); + if (strncmp( p, "Atari ", 6 ) == 0) + atari_format = 1; + break; + } + } + fclose( f ); +#endif +} + + +int main(int argc,char **argv) +{ + DOS_FS fs; + int rw,salvage_files,verify,c; + unsigned long free_clusters; + + rw = salvage_files = verify = 0; + interactive = 1; + check_atari(); + + while ((c = getopt(argc,argv,"Aad:flnrtu:vVwy")) != EOF) + switch (c) { + case 'A': /* toggle Atari format */ + atari_format = !atari_format; + break; + case 'a': + case 'y': + rw = 1; + interactive = 0; + salvage_files = 1; + break; + case 'd': + file_add(optarg,fdt_drop); + break; + case 'f': + salvage_files = 1; + break; + case 'l': + list = 1; + break; + case 'n': + rw = 0; + interactive = 0; + break; + case 'r': + rw = 1; + interactive = 1; + break; + case 't': + test = 1; + break; + case 'u': + file_add(optarg,fdt_undelete); + break; + case 'v': + verbose = 1; + printf("dosfsck " VERSION " (" VERSION_DATE ")\n"); + break; + case 'V': + verify = 1; + break; + case 'w': + write_immed = 1; + break; + default: + usage(argv[0]); + } + + if ((test || write_immed) && !rw) { + fprintf(stderr,"-t and -w require -a or -r\n"); + exit(2); + } + if (optind != argc-1) usage(argv[0]); + + printf( "dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n" ); + fs_open(argv[optind],rw); + read_boot(&fs); + if (verify) printf("Starting check/repair pass.\n"); + while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue); + if (test) fix_bad(&fs); + if (salvage_files) reclaim_file(&fs); + else reclaim_free(&fs); + free_clusters = update_free(&fs); + file_unused(); + qfree(&mem_queue); + if (verify) { + printf("Starting verification pass.\n"); + read_fat(&fs); + scan_root(&fs); + reclaim_free(&fs); + qfree(&mem_queue); + } + + if (fs_changed()) { + if (rw) { + if (interactive) + rw = get_key("yn","Perform changes ? (y/n)") == 'y'; + else printf("Performing changes.\n"); + } + else + printf("Leaving file system unchanged.\n"); + } + + printf( "%s: %u files, %lu/%lu clusters\n", argv[optind], + n_files, fs.clusters - free_clusters, fs.clusters ); + + return fs_close(rw) ? 1 : 0; +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/dosfsck.h b/rosapps/sysutils/dosfsck/dosfsck.h index 6fcc5b50dd1..8fc1b3480a0 100644 --- a/rosapps/sysutils/dosfsck/dosfsck.h +++ b/rosapps/sysutils/dosfsck/dosfsck.h @@ -1,187 +1,187 @@ -/* dosfsck.h - Common data structures and global variables */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#ifndef _DOSFSCK_H -#define _DOSFSCK_H - -//#include "types.h" - -#ifdef _WIN32 - -typedef unsigned char __u8; -typedef unsigned short __u16; -typedef unsigned int __u32; -typedef unsigned __int64 __u64; -typedef unsigned short __le16; -typedef unsigned int __le32; -typedef __int64 loff_t; -typedef __int64 ll_t; - -#define CF_LE_W(v) (v) -#define CF_LE_L(v) (v) -#define CT_LE_W(v) (v) -#define CT_LE_L(v) (v) - -#endif - -#define _LINUX_STAT_H /* hack to avoid inclusion of */ -#define _LINUX_STRING_H_ /* hack to avoid inclusion of */ -#define _LINUX_FS_H /* hack to avoid inclusion of */ - -//#include -//# include "types.h" -# include "byteorder.h" - -#include "msdos_fs.h" - -#if 0 -#undef CF_LE_W -#undef CF_LE_L -#undef CT_LE_W -#undef CT_LE_L -#endif - -#if __BYTE_ORDER == __BIG_ENDIAN -#include "byteswap.h" -#if 0 -#define CF_LE_W(v) bswap_16(v) -#define CF_LE_L(v) bswap_32(v) -#define CT_LE_W(v) CF_LE_W(v) -#define CT_LE_L(v) CF_LE_L(v) -#endif -#else -#define CF_LE_W(v) (v) -#define CF_LE_L(v) (v) -#define CT_LE_W(v) (v) -#define CT_LE_L(v) (v) -#endif /* __BIG_ENDIAN */ - -#define VFAT_LN_ATTR (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) - -#include - -/* ++roman: Use own definition of boot sector structure -- the kernel headers' - * name for it is msdos_boot_sector in 2.0 and fat_boot_sector in 2.1 ... */ -struct boot_sector { - __u8 ignored[3]; /* Boot strap short or near jump */ - __u8 system_id[8]; /* Name - can be used to special case - partition manager volumes */ - __u8 sector_size[2]; /* bytes per logical sector */ - __u8 cluster_size; /* sectors/cluster */ - __u16 reserved; /* reserved sectors */ - __u8 fats; /* number of FATs */ - __u8 dir_entries[2]; /* root directory entries */ - __u8 sectors[2]; /* number of sectors */ - __u8 media; /* media code (unused) */ - __u16 fat_length; /* sectors/FAT */ - __u16 secs_track; /* sectors per track */ - __u16 heads; /* number of heads */ - __u32 hidden; /* hidden sectors (unused) */ - __u32 total_sect; /* number of sectors (if sectors == 0) */ - - /* The following fields are only used by FAT32 */ - __u32 fat32_length; /* sectors/FAT */ - __u16 flags; /* bit 8: fat mirroring, low 4: active fat */ - __u8 version[2]; /* major, minor filesystem version */ - __u32 root_cluster; /* first cluster in root directory */ - __u16 info_sector; /* filesystem info sector */ - __u16 backup_boot; /* backup boot sector */ - __u16 reserved2[6]; /* Unused */ - - /* fill up to 512 bytes */ - __u8 junk[448]; -}; - -#include - -struct info_sector { - __u32 magic; /* Magic for info sector ('RRaA') */ - __u8 junk[0x1dc]; - __u32 reserved1; /* Nothing as far as I can tell */ - __u32 signature; /* 0x61417272 ('rrAa') */ - __u32 free_clusters; /* Free cluster count. -1 if unknown */ - __u32 next_cluster; /* Most recently allocated cluster. */ - __u32 reserved2[3]; - __u16 reserved3; - __u16 boot_sign; -}; - -typedef struct { - __u8 name[8],ext[3]; /* name and extension */ - __u8 attr; /* attribute bits */ - __u8 lcase; /* Case for base and extension */ - __u8 ctime_ms; /* Creation time, milliseconds */ - __u16 ctime; /* Creation time */ - __u16 cdate; /* Creation date */ - __u16 adate; /* Last access date */ - __u16 starthi; /* High 16 bits of cluster in FAT32 */ - __u16 time,date,start;/* time, date and first cluster */ - __u32 size; /* file size (in bytes) */ -} DIR_ENT; - -typedef struct _dos_file { - DIR_ENT dir_ent; - char *lfn; - loff_t offset; - struct _dos_file *parent; /* parent directory */ - struct _dos_file *next; /* next entry */ - struct _dos_file *first; /* first entry (directory only) */ -} DOS_FILE; - -typedef struct { - unsigned long value; - unsigned long reserved; - DOS_FILE *owner; - int prev; /* number of previous clusters */ -} FAT_ENTRY; - -typedef struct { - int nfats; - loff_t fat_start; - unsigned int fat_size; /* unit is bytes */ - unsigned int fat_bits; /* size of a FAT entry */ - unsigned int eff_fat_bits; /* # of used bits in a FAT entry */ - unsigned long root_cluster; /* 0 for old-style root dir */ - loff_t root_start; - unsigned int root_entries; - loff_t data_start; - unsigned int cluster_size; - unsigned long clusters; - loff_t fsinfo_start; /* 0 if not present */ - long free_clusters; - loff_t backupboot_start; /* 0 if not present */ - FAT_ENTRY *fat; -} DOS_FS; - -#ifndef offsetof -#define offsetof(t,e) ((int)&(((t *)0)->e)) -#endif - -extern int interactive,list,verbose,test,write_immed; -extern int atari_format; -extern unsigned n_files; -extern void *mem_queue; - -/* value to use as end-of-file marker */ -#define FAT_EOF(fs) ((atari_format ? 0xfff : 0xff8) | FAT_EXTD(fs)) -#define FAT_IS_EOF(fs,v) ((unsigned long)(v) >= (0xff8|FAT_EXTD(fs))) -/* value to mark bad clusters */ -#define FAT_BAD(fs) (0xff7 | FAT_EXTD(fs)) -/* range of values used for bad clusters */ -#define FAT_MIN_BAD(fs) ((atari_format ? 0xff0 : 0xff7) | FAT_EXTD(fs)) -#define FAT_MAX_BAD(fs) ((atari_format ? 0xff7 : 0xff7) | FAT_EXTD(fs)) -#define FAT_IS_BAD(fs,v) ((v) >= FAT_MIN_BAD(fs) && (v) <= FAT_MAX_BAD(fs)) - -/* return -16 as a number with fs->fat_bits bits */ -#define FAT_EXTD(fs) (((1 << fs->eff_fat_bits)-1) & ~0xf) - -#endif - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +/* dosfsck.h - Common data structures and global variables */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#ifndef _DOSFSCK_H +#define _DOSFSCK_H + +//#include "types.h" + +#ifdef _WIN32 + +typedef unsigned char __u8; +typedef unsigned short __u16; +typedef unsigned int __u32; +typedef unsigned __int64 __u64; +typedef unsigned short __le16; +typedef unsigned int __le32; +typedef __int64 loff_t; +typedef __int64 ll_t; + +#define CF_LE_W(v) (v) +#define CF_LE_L(v) (v) +#define CT_LE_W(v) (v) +#define CT_LE_L(v) (v) + +#endif + +#define _LINUX_STAT_H /* hack to avoid inclusion of */ +#define _LINUX_STRING_H_ /* hack to avoid inclusion of */ +#define _LINUX_FS_H /* hack to avoid inclusion of */ + +//#include +//# include "types.h" +# include "byteorder.h" + +#include "msdos_fs.h" + +#if 0 +#undef CF_LE_W +#undef CF_LE_L +#undef CT_LE_W +#undef CT_LE_L +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN +#include "byteswap.h" +#if 0 +#define CF_LE_W(v) bswap_16(v) +#define CF_LE_L(v) bswap_32(v) +#define CT_LE_W(v) CF_LE_W(v) +#define CT_LE_L(v) CF_LE_L(v) +#endif +#else +#define CF_LE_W(v) (v) +#define CF_LE_L(v) (v) +#define CT_LE_W(v) (v) +#define CT_LE_L(v) (v) +#endif /* __BIG_ENDIAN */ + +#define VFAT_LN_ATTR (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) + +#include + +/* ++roman: Use own definition of boot sector structure -- the kernel headers' + * name for it is msdos_boot_sector in 2.0 and fat_boot_sector in 2.1 ... */ +struct boot_sector { + __u8 ignored[3]; /* Boot strap short or near jump */ + __u8 system_id[8]; /* Name - can be used to special case + partition manager volumes */ + __u8 sector_size[2]; /* bytes per logical sector */ + __u8 cluster_size; /* sectors/cluster */ + __u16 reserved; /* reserved sectors */ + __u8 fats; /* number of FATs */ + __u8 dir_entries[2]; /* root directory entries */ + __u8 sectors[2]; /* number of sectors */ + __u8 media; /* media code (unused) */ + __u16 fat_length; /* sectors/FAT */ + __u16 secs_track; /* sectors per track */ + __u16 heads; /* number of heads */ + __u32 hidden; /* hidden sectors (unused) */ + __u32 total_sect; /* number of sectors (if sectors == 0) */ + + /* The following fields are only used by FAT32 */ + __u32 fat32_length; /* sectors/FAT */ + __u16 flags; /* bit 8: fat mirroring, low 4: active fat */ + __u8 version[2]; /* major, minor filesystem version */ + __u32 root_cluster; /* first cluster in root directory */ + __u16 info_sector; /* filesystem info sector */ + __u16 backup_boot; /* backup boot sector */ + __u16 reserved2[6]; /* Unused */ + + /* fill up to 512 bytes */ + __u8 junk[448]; +}; + +#include + +struct info_sector { + __u32 magic; /* Magic for info sector ('RRaA') */ + __u8 junk[0x1dc]; + __u32 reserved1; /* Nothing as far as I can tell */ + __u32 signature; /* 0x61417272 ('rrAa') */ + __u32 free_clusters; /* Free cluster count. -1 if unknown */ + __u32 next_cluster; /* Most recently allocated cluster. */ + __u32 reserved2[3]; + __u16 reserved3; + __u16 boot_sign; +}; + +typedef struct { + __u8 name[8],ext[3]; /* name and extension */ + __u8 attr; /* attribute bits */ + __u8 lcase; /* Case for base and extension */ + __u8 ctime_ms; /* Creation time, milliseconds */ + __u16 ctime; /* Creation time */ + __u16 cdate; /* Creation date */ + __u16 adate; /* Last access date */ + __u16 starthi; /* High 16 bits of cluster in FAT32 */ + __u16 time,date,start;/* time, date and first cluster */ + __u32 size; /* file size (in bytes) */ +} DIR_ENT; + +typedef struct _dos_file { + DIR_ENT dir_ent; + char *lfn; + loff_t offset; + struct _dos_file *parent; /* parent directory */ + struct _dos_file *next; /* next entry */ + struct _dos_file *first; /* first entry (directory only) */ +} DOS_FILE; + +typedef struct { + unsigned long value; + unsigned long reserved; + DOS_FILE *owner; + int prev; /* number of previous clusters */ +} FAT_ENTRY; + +typedef struct { + int nfats; + loff_t fat_start; + unsigned int fat_size; /* unit is bytes */ + unsigned int fat_bits; /* size of a FAT entry */ + unsigned int eff_fat_bits; /* # of used bits in a FAT entry */ + unsigned long root_cluster; /* 0 for old-style root dir */ + loff_t root_start; + unsigned int root_entries; + loff_t data_start; + unsigned int cluster_size; + unsigned long clusters; + loff_t fsinfo_start; /* 0 if not present */ + long free_clusters; + loff_t backupboot_start; /* 0 if not present */ + FAT_ENTRY *fat; +} DOS_FS; + +#ifndef offsetof +#define offsetof(t,e) ((int)&(((t *)0)->e)) +#endif + +extern int interactive,list,verbose,test,write_immed; +extern int atari_format; +extern unsigned n_files; +extern void *mem_queue; + +/* value to use as end-of-file marker */ +#define FAT_EOF(fs) ((atari_format ? 0xfff : 0xff8) | FAT_EXTD(fs)) +#define FAT_IS_EOF(fs,v) ((unsigned long)(v) >= (0xff8|FAT_EXTD(fs))) +/* value to mark bad clusters */ +#define FAT_BAD(fs) (0xff7 | FAT_EXTD(fs)) +/* range of values used for bad clusters */ +#define FAT_MIN_BAD(fs) ((atari_format ? 0xff0 : 0xff7) | FAT_EXTD(fs)) +#define FAT_MAX_BAD(fs) ((atari_format ? 0xff7 : 0xff7) | FAT_EXTD(fs)) +#define FAT_IS_BAD(fs,v) ((v) >= FAT_MIN_BAD(fs) && (v) <= FAT_MAX_BAD(fs)) + +/* return -16 as a number with fs->fat_bits bits */ +#define FAT_EXTD(fs) (((1 << fs->eff_fat_bits)-1) & ~0xf) + +#endif + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/fat.c b/rosapps/sysutils/dosfsck/fat.c index 5f29d5f2a54..1975a12ad3d 100644 --- a/rosapps/sysutils/dosfsck/fat.c +++ b/rosapps/sysutils/dosfsck/fat.c @@ -1,366 +1,366 @@ -/* fat.c - Read/write access to the FAT */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#include -#include -#include -//#include - -#include "common.h" -#include "dosfsck.h" -#include "io.h" -#include "check.h" -#include "fat.h" - -#pragma warning(disable: 4018) - -static void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs) -{ - unsigned char *ptr; - - switch(fs->fat_bits) { - case 12: - ptr = &((unsigned char *) fat)[cluster*3/2]; - entry->value = 0xfff & (cluster & 1 ? (ptr[0] >> 4) | (ptr[1] << 4) : - (ptr[0] | ptr[1] << 8)); - break; - case 16: - entry->value = CF_LE_W(((unsigned short *) fat)[cluster]); - break; - case 32: - /* According to M$, the high 4 bits of a FAT32 entry are reserved and - * are not part of the cluster number. So we cut them off. */ - { - unsigned long e = CF_LE_L(((unsigned int *) fat)[cluster]); - entry->value = e & 0xfffffff; - entry->reserved = e >> 28; - } - break; - default: - die("Bad FAT entry size: %d bits.",fs->fat_bits); - } - entry->owner = NULL; -} - - -void read_fat(DOS_FS *fs) -{ - int eff_size; - unsigned long i; - void *first,*second,*use; - int first_ok,second_ok; - - eff_size = ((fs->clusters+2)*fs->fat_bits+7)/8; - // TMN: Must round up to disk-sector boundary. For now, assume 512-byte disk. - if (eff_size % 512) { - eff_size += 512 - (eff_size % 512); - } - first = alloc(eff_size); - fs_read(fs->fat_start,eff_size,first); - use = first; - if (fs->nfats > 1) { - second = alloc(eff_size); - fs_read(fs->fat_start+fs->fat_size,eff_size,second); - } - else - second = NULL; - if (second && memcmp(first,second,eff_size) != 0) { - FAT_ENTRY first_media, second_media; - get_fat(&first_media,first,0,fs); - get_fat(&second_media,second,0,fs); - first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); - second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); - if (first_ok && !second_ok) { - printf("FATs differ - using first FAT.\n"); - fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); - } - if (!first_ok && second_ok) { - printf("FATs differ - using second FAT.\n"); - fs_write(fs->fat_start,eff_size,use = second); - } - if (first_ok && second_ok) { - if (interactive) { - printf("FATs differ but appear to be intact. Use which FAT ?\n" - "1) Use first FAT\n2) Use second FAT\n"); - if (get_key("12","?") == '1') - fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); - else fs_write(fs->fat_start,eff_size,use = second); - } - else { - printf("FATs differ but appear to be intact. Using first " - "FAT.\n"); - fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); - } - } - if (!first_ok && !second_ok) { - printf("Both FATs appear to be corrupt. Giving up.\n"); - exit(1); - } - } - fs->fat = qalloc(&mem_queue,sizeof(FAT_ENTRY)*(fs->clusters+2)); - for (i = 2; i < fs->clusters+2; i++) get_fat(&fs->fat[i],use,i,fs); - for (i = 2; i < fs->clusters+2; i++) - if (fs->fat[i].value >= fs->clusters+2 && - (fs->fat[i].value < FAT_MIN_BAD(fs))) { - printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n", - i-2,fs->fat[i].value,fs->clusters+2-1); - set_fat(fs,i,-1); - } - free(first); - if (second) - free(second); -} - - -void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new) -{ - unsigned char data[4]; - int size; - loff_t offs; - - if ((long)new == -1) - new = FAT_EOF(fs); - else if ((long)new == -2) - new = FAT_BAD(fs); - switch( fs->fat_bits ) { - case 12: - offs = fs->fat_start+cluster*3/2; - if (cluster & 1) { - data[0] = ((new & 0xf) << 4) | (fs->fat[cluster-1].value >> 8); - data[1] = new >> 4; - } - else { - data[0] = new & 0xff; - data[1] = (new >> 8) | (cluster == fs->clusters-1 ? 0 : - (0xff & fs->fat[cluster+1].value) << 4); - } - size = 2; - break; - case 16: - offs = fs->fat_start+cluster*2; - *(unsigned short *) data = CT_LE_W(new); - size = 2; - break; - case 32: - offs = fs->fat_start+cluster*4; - /* According to M$, the high 4 bits of a FAT32 entry are reserved and - * are not part of the cluster number. So we never touch them. */ - *(unsigned long *) data = CT_LE_L( (new & 0xfffffff) | - (fs->fat[cluster].reserved << 28) ); - size = 4; - break; - default: - die("Bad FAT entry size: %d bits.",fs->fat_bits); - } - fs->fat[cluster].value = new; - fs_write(offs,size,&data); - fs_write(offs+fs->fat_size,size,&data); -} - - -int bad_cluster(DOS_FS *fs,unsigned long cluster) -{ - return FAT_IS_BAD(fs,fs->fat[cluster].value); -} - - -unsigned long next_cluster(DOS_FS *fs,unsigned long cluster) -{ - unsigned long value; - - value = fs->fat[cluster].value; - if (FAT_IS_BAD(fs,value)) - die("Internal error: next_cluster on bad cluster"); - return FAT_IS_EOF(fs,value) ? -1 : value; -} - - -loff_t cluster_start(DOS_FS *fs,unsigned long cluster) -{ - return fs->data_start+((loff_t)cluster-2)*fs->cluster_size; -} - - -void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner) -{ - if (owner && fs->fat[cluster].owner) - die("Internal error: attempt to change file owner"); - fs->fat[cluster].owner = owner; -} - - -DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster) -{ - return fs->fat[cluster].owner; -} - - -void fix_bad(DOS_FS *fs) -{ - unsigned long i; - - if (verbose) - printf("Checking for bad clusters.\n"); - for (i = 2; i < fs->clusters+2; i++) - if (!get_owner(fs,i) && !FAT_IS_BAD(fs,fs->fat[i].value)) - if (!fs_test(cluster_start(fs,i),fs->cluster_size)) { - printf("Cluster %lu is unreadable.\n",i); - set_fat(fs,i,-2); - } -} - - -void reclaim_free(DOS_FS *fs) -{ - int reclaimed; - unsigned long i; - - if (verbose) - printf("Checking for unused clusters.\n"); - reclaimed = 0; - for (i = 2; i < fs->clusters+2; i++) - if (!get_owner(fs,i) && fs->fat[i].value && - !FAT_IS_BAD(fs,fs->fat[i].value)) { - set_fat(fs,i,0); - reclaimed++; - } - if (reclaimed) - printf("Reclaimed %d unused cluster%s (%d bytes).\n",reclaimed, - reclaimed == 1 ? "" : "s",reclaimed*fs->cluster_size); -} - - -static void tag_free(DOS_FS *fs,DOS_FILE *ptr) -{ - DOS_FILE *owner; - int prev; - unsigned long i,walk; - - for (i = 2; i < fs->clusters+2; i++) - if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) && - !get_owner(fs,i) && !fs->fat[i].prev) { - prev = 0; - for (walk = i; walk > 0 && walk != -1; - walk = next_cluster(fs,walk)) { - if (!(owner = get_owner(fs,walk))) set_owner(fs,walk,ptr); - else if (owner != ptr) - die("Internal error: free chain collides with file"); - else { - set_fat(fs,prev,-1); - break; - } - prev = walk; - } - } -} - - -void reclaim_file(DOS_FS *fs) -{ - DOS_FILE dummy; - int reclaimed,files,changed; - unsigned long i,next,walk; - - if (verbose) - printf("Reclaiming unconnected clusters.\n"); - for (i = 2; i < fs->clusters+2; i++) fs->fat[i].prev = 0; - for (i = 2; i < fs->clusters+2; i++) { - next = fs->fat[i].value; - if (!get_owner(fs,i) && next && next < fs->clusters+2) { - if (get_owner(fs,next) || !fs->fat[next].value || - FAT_IS_BAD(fs,fs->fat[next].value)) set_fat(fs,i,-1); - else fs->fat[next].prev++; - } - } - do { - tag_free(fs,&dummy); - changed = 0; - for (i = 2; i < fs->clusters+2; i++) - if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) && - !get_owner(fs, i)) { - if (!fs->fat[fs->fat[i].value].prev--) - die("Internal error: prev going below zero"); - set_fat(fs,i,-1); - changed = 1; - printf("Broke cycle at cluster %lu in free chain.\n",i); - break; - } - } - while (changed); - files = reclaimed = 0; - for (i = 2; i < fs->clusters+2; i++) - if (get_owner(fs,i) == &dummy && !fs->fat[i].prev) { - DIR_ENT de; - loff_t offset; - files++; - offset = alloc_rootdir_entry(fs,&de,"FSCK%04dREC"); - de.start = CT_LE_W(i&0xffff); - if (fs->fat_bits == 32) - de.starthi = CT_LE_W(i>>16); - for (walk = i; walk > 0 && walk != -1; - walk = next_cluster(fs,walk)) { - de.size = CT_LE_L(CF_LE_L(de.size)+fs->cluster_size); - reclaimed++; - } - fs_write(offset,sizeof(DIR_ENT),&de); - } - if (reclaimed) - printf("Reclaimed %d unused cluster%s (%d bytes) in %d chain%s.\n", - reclaimed,reclaimed == 1 ? "" : "s",reclaimed*fs->cluster_size,files, - files == 1 ? "" : "s"); -} - - -unsigned long update_free(DOS_FS *fs) -{ - unsigned long i; - unsigned long free = 0; - int do_set = 0; - - for (i = 2; i < fs->clusters+2; i++) - if (!get_owner(fs,i) && !FAT_IS_BAD(fs,fs->fat[i].value)) - ++free; - - if (!fs->fsinfo_start) - return free; - - if (verbose) - printf("Checking free cluster summary.\n"); - if (fs->free_clusters >= 0) { - if (free != fs->free_clusters) { - printf( "Free cluster summary wrong (%ld vs. really %ld)\n", - fs->free_clusters,free); - if (interactive) - printf( "1) Correct\n2) Don't correct\n" ); - else printf( " Auto-correcting.\n" ); - if (!interactive || get_key("12","?") == '1') - do_set = 1; - } - } - else { - printf( "Free cluster summary uninitialized (should be %ld)\n", free ); - if (interactive) - printf( "1) Set it\n2) Leave it uninitialized\n" ); - else printf( " Auto-setting.\n" ); - if (!interactive || get_key("12","?") == '1') - do_set = 1; - } - - if (do_set) { - fs->free_clusters = free; - free = CT_LE_L(free); - fs_write(fs->fsinfo_start+offsetof(struct info_sector,free_clusters), - sizeof(free),&free); - } - - return free; -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +/* fat.c - Read/write access to the FAT */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#include +#include +#include +//#include + +#include "common.h" +#include "dosfsck.h" +#include "io.h" +#include "check.h" +#include "fat.h" + +#pragma warning(disable: 4018) + +static void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs) +{ + unsigned char *ptr; + + switch(fs->fat_bits) { + case 12: + ptr = &((unsigned char *) fat)[cluster*3/2]; + entry->value = 0xfff & (cluster & 1 ? (ptr[0] >> 4) | (ptr[1] << 4) : + (ptr[0] | ptr[1] << 8)); + break; + case 16: + entry->value = CF_LE_W(((unsigned short *) fat)[cluster]); + break; + case 32: + /* According to M$, the high 4 bits of a FAT32 entry are reserved and + * are not part of the cluster number. So we cut them off. */ + { + unsigned long e = CF_LE_L(((unsigned int *) fat)[cluster]); + entry->value = e & 0xfffffff; + entry->reserved = e >> 28; + } + break; + default: + die("Bad FAT entry size: %d bits.",fs->fat_bits); + } + entry->owner = NULL; +} + + +void read_fat(DOS_FS *fs) +{ + int eff_size; + unsigned long i; + void *first,*second,*use; + int first_ok,second_ok; + + eff_size = ((fs->clusters+2)*fs->fat_bits+7)/8; + // TMN: Must round up to disk-sector boundary. For now, assume 512-byte disk. + if (eff_size % 512) { + eff_size += 512 - (eff_size % 512); + } + first = alloc(eff_size); + fs_read(fs->fat_start,eff_size,first); + use = first; + if (fs->nfats > 1) { + second = alloc(eff_size); + fs_read(fs->fat_start+fs->fat_size,eff_size,second); + } + else + second = NULL; + if (second && memcmp(first,second,eff_size) != 0) { + FAT_ENTRY first_media, second_media; + get_fat(&first_media,first,0,fs); + get_fat(&second_media,second,0,fs); + first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); + second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); + if (first_ok && !second_ok) { + printf("FATs differ - using first FAT.\n"); + fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); + } + if (!first_ok && second_ok) { + printf("FATs differ - using second FAT.\n"); + fs_write(fs->fat_start,eff_size,use = second); + } + if (first_ok && second_ok) { + if (interactive) { + printf("FATs differ but appear to be intact. Use which FAT ?\n" + "1) Use first FAT\n2) Use second FAT\n"); + if (get_key("12","?") == '1') + fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); + else fs_write(fs->fat_start,eff_size,use = second); + } + else { + printf("FATs differ but appear to be intact. Using first " + "FAT.\n"); + fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); + } + } + if (!first_ok && !second_ok) { + printf("Both FATs appear to be corrupt. Giving up.\n"); + exit(1); + } + } + fs->fat = qalloc(&mem_queue,sizeof(FAT_ENTRY)*(fs->clusters+2)); + for (i = 2; i < fs->clusters+2; i++) get_fat(&fs->fat[i],use,i,fs); + for (i = 2; i < fs->clusters+2; i++) + if (fs->fat[i].value >= fs->clusters+2 && + (fs->fat[i].value < FAT_MIN_BAD(fs))) { + printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n", + i-2,fs->fat[i].value,fs->clusters+2-1); + set_fat(fs,i,-1); + } + free(first); + if (second) + free(second); +} + + +void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new) +{ + unsigned char data[4]; + int size; + loff_t offs; + + if ((long)new == -1) + new = FAT_EOF(fs); + else if ((long)new == -2) + new = FAT_BAD(fs); + switch( fs->fat_bits ) { + case 12: + offs = fs->fat_start+cluster*3/2; + if (cluster & 1) { + data[0] = ((new & 0xf) << 4) | (fs->fat[cluster-1].value >> 8); + data[1] = new >> 4; + } + else { + data[0] = new & 0xff; + data[1] = (new >> 8) | (cluster == fs->clusters-1 ? 0 : + (0xff & fs->fat[cluster+1].value) << 4); + } + size = 2; + break; + case 16: + offs = fs->fat_start+cluster*2; + *(unsigned short *) data = CT_LE_W(new); + size = 2; + break; + case 32: + offs = fs->fat_start+cluster*4; + /* According to M$, the high 4 bits of a FAT32 entry are reserved and + * are not part of the cluster number. So we never touch them. */ + *(unsigned long *) data = CT_LE_L( (new & 0xfffffff) | + (fs->fat[cluster].reserved << 28) ); + size = 4; + break; + default: + die("Bad FAT entry size: %d bits.",fs->fat_bits); + } + fs->fat[cluster].value = new; + fs_write(offs,size,&data); + fs_write(offs+fs->fat_size,size,&data); +} + + +int bad_cluster(DOS_FS *fs,unsigned long cluster) +{ + return FAT_IS_BAD(fs,fs->fat[cluster].value); +} + + +unsigned long next_cluster(DOS_FS *fs,unsigned long cluster) +{ + unsigned long value; + + value = fs->fat[cluster].value; + if (FAT_IS_BAD(fs,value)) + die("Internal error: next_cluster on bad cluster"); + return FAT_IS_EOF(fs,value) ? -1 : value; +} + + +loff_t cluster_start(DOS_FS *fs,unsigned long cluster) +{ + return fs->data_start+((loff_t)cluster-2)*fs->cluster_size; +} + + +void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner) +{ + if (owner && fs->fat[cluster].owner) + die("Internal error: attempt to change file owner"); + fs->fat[cluster].owner = owner; +} + + +DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster) +{ + return fs->fat[cluster].owner; +} + + +void fix_bad(DOS_FS *fs) +{ + unsigned long i; + + if (verbose) + printf("Checking for bad clusters.\n"); + for (i = 2; i < fs->clusters+2; i++) + if (!get_owner(fs,i) && !FAT_IS_BAD(fs,fs->fat[i].value)) + if (!fs_test(cluster_start(fs,i),fs->cluster_size)) { + printf("Cluster %lu is unreadable.\n",i); + set_fat(fs,i,-2); + } +} + + +void reclaim_free(DOS_FS *fs) +{ + int reclaimed; + unsigned long i; + + if (verbose) + printf("Checking for unused clusters.\n"); + reclaimed = 0; + for (i = 2; i < fs->clusters+2; i++) + if (!get_owner(fs,i) && fs->fat[i].value && + !FAT_IS_BAD(fs,fs->fat[i].value)) { + set_fat(fs,i,0); + reclaimed++; + } + if (reclaimed) + printf("Reclaimed %d unused cluster%s (%d bytes).\n",reclaimed, + reclaimed == 1 ? "" : "s",reclaimed*fs->cluster_size); +} + + +static void tag_free(DOS_FS *fs,DOS_FILE *ptr) +{ + DOS_FILE *owner; + int prev; + unsigned long i,walk; + + for (i = 2; i < fs->clusters+2; i++) + if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) && + !get_owner(fs,i) && !fs->fat[i].prev) { + prev = 0; + for (walk = i; walk > 0 && walk != -1; + walk = next_cluster(fs,walk)) { + if (!(owner = get_owner(fs,walk))) set_owner(fs,walk,ptr); + else if (owner != ptr) + die("Internal error: free chain collides with file"); + else { + set_fat(fs,prev,-1); + break; + } + prev = walk; + } + } +} + + +void reclaim_file(DOS_FS *fs) +{ + DOS_FILE dummy; + int reclaimed,files,changed; + unsigned long i,next,walk; + + if (verbose) + printf("Reclaiming unconnected clusters.\n"); + for (i = 2; i < fs->clusters+2; i++) fs->fat[i].prev = 0; + for (i = 2; i < fs->clusters+2; i++) { + next = fs->fat[i].value; + if (!get_owner(fs,i) && next && next < fs->clusters+2) { + if (get_owner(fs,next) || !fs->fat[next].value || + FAT_IS_BAD(fs,fs->fat[next].value)) set_fat(fs,i,-1); + else fs->fat[next].prev++; + } + } + do { + tag_free(fs,&dummy); + changed = 0; + for (i = 2; i < fs->clusters+2; i++) + if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) && + !get_owner(fs, i)) { + if (!fs->fat[fs->fat[i].value].prev--) + die("Internal error: prev going below zero"); + set_fat(fs,i,-1); + changed = 1; + printf("Broke cycle at cluster %lu in free chain.\n",i); + break; + } + } + while (changed); + files = reclaimed = 0; + for (i = 2; i < fs->clusters+2; i++) + if (get_owner(fs,i) == &dummy && !fs->fat[i].prev) { + DIR_ENT de; + loff_t offset; + files++; + offset = alloc_rootdir_entry(fs,&de,"FSCK%04dREC"); + de.start = CT_LE_W(i&0xffff); + if (fs->fat_bits == 32) + de.starthi = CT_LE_W(i>>16); + for (walk = i; walk > 0 && walk != -1; + walk = next_cluster(fs,walk)) { + de.size = CT_LE_L(CF_LE_L(de.size)+fs->cluster_size); + reclaimed++; + } + fs_write(offset,sizeof(DIR_ENT),&de); + } + if (reclaimed) + printf("Reclaimed %d unused cluster%s (%d bytes) in %d chain%s.\n", + reclaimed,reclaimed == 1 ? "" : "s",reclaimed*fs->cluster_size,files, + files == 1 ? "" : "s"); +} + + +unsigned long update_free(DOS_FS *fs) +{ + unsigned long i; + unsigned long free = 0; + int do_set = 0; + + for (i = 2; i < fs->clusters+2; i++) + if (!get_owner(fs,i) && !FAT_IS_BAD(fs,fs->fat[i].value)) + ++free; + + if (!fs->fsinfo_start) + return free; + + if (verbose) + printf("Checking free cluster summary.\n"); + if (fs->free_clusters >= 0) { + if (free != fs->free_clusters) { + printf( "Free cluster summary wrong (%ld vs. really %ld)\n", + fs->free_clusters,free); + if (interactive) + printf( "1) Correct\n2) Don't correct\n" ); + else printf( " Auto-correcting.\n" ); + if (!interactive || get_key("12","?") == '1') + do_set = 1; + } + } + else { + printf( "Free cluster summary uninitialized (should be %ld)\n", free ); + if (interactive) + printf( "1) Set it\n2) Leave it uninitialized\n" ); + else printf( " Auto-setting.\n" ); + if (!interactive || get_key("12","?") == '1') + do_set = 1; + } + + if (do_set) { + fs->free_clusters = free; + free = CT_LE_L(free); + fs_write(fs->fsinfo_start+offsetof(struct info_sector,free_clusters), + sizeof(free),&free); + } + + return free; +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/fat.h b/rosapps/sysutils/dosfsck/fat.h index 32b23de459b..8c2312d9e64 100644 --- a/rosapps/sysutils/dosfsck/fat.h +++ b/rosapps/sysutils/dosfsck/fat.h @@ -1,64 +1,64 @@ -/* fat.h - Read/write access to the FAT */ - -/* Written 1993 by Werner Almesberger */ - - -#ifndef _FAT_H -#define _FAT_H - -void read_fat(DOS_FS *fs); - -/* Loads the FAT of the file system described by FS. Initializes the FAT, - replaces broken FATs and rejects invalid cluster entries. */ - -void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new); - -/* Changes the value of the CLUSTERth cluster of the FAT of FS to NEW. Special - values of NEW are -1 (EOF, 0xff8 or 0xfff8) and -2 (bad sector, 0xff7 or - 0xfff7) */ - -int bad_cluster(DOS_FS *fs,unsigned long cluster); - -/* Returns a non-zero integer if the CLUSTERth cluster is marked as bad or zero - otherwise. */ - -unsigned long next_cluster(DOS_FS *fs,unsigned long cluster); - -/* Returns the number of the cluster following CLUSTER, or -1 if this is the - last cluster of the respective cluster chain. CLUSTER must not be a bad - cluster. */ - -loff_t cluster_start(DOS_FS *fs,unsigned long cluster); - -/* Returns the byte offset of CLUSTER, relative to the respective device. */ - -void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner); - -/* Sets the owner pointer of the respective cluster to OWNER. If OWNER was NULL - before, it can be set to NULL or any non-NULL value. Otherwise, only NULL is - accepted as the new value. */ - -DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster); - -/* Returns the owner of the repective cluster or NULL if the cluster has no - owner. */ - -void fix_bad(DOS_FS *fs); - -/* Scans the disk for currently unused bad clusters and marks them as bad. */ - -void reclaim_free(DOS_FS *fs); - -/* Marks all allocated, but unused clusters as free. */ - -void reclaim_file(DOS_FS *fs); - -/* Scans the FAT for chains of allocated, but unused clusters and creates files - for them in the root directory. Also tries to fix all inconsistencies (e.g. - loops, shared clusters, etc.) in the process. */ - -unsigned long update_free(DOS_FS *fs); - -/* Updates free cluster count in FSINFO sector. */ - -#endif +/* fat.h - Read/write access to the FAT */ + +/* Written 1993 by Werner Almesberger */ + + +#ifndef _FAT_H +#define _FAT_H + +void read_fat(DOS_FS *fs); + +/* Loads the FAT of the file system described by FS. Initializes the FAT, + replaces broken FATs and rejects invalid cluster entries. */ + +void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new); + +/* Changes the value of the CLUSTERth cluster of the FAT of FS to NEW. Special + values of NEW are -1 (EOF, 0xff8 or 0xfff8) and -2 (bad sector, 0xff7 or + 0xfff7) */ + +int bad_cluster(DOS_FS *fs,unsigned long cluster); + +/* Returns a non-zero integer if the CLUSTERth cluster is marked as bad or zero + otherwise. */ + +unsigned long next_cluster(DOS_FS *fs,unsigned long cluster); + +/* Returns the number of the cluster following CLUSTER, or -1 if this is the + last cluster of the respective cluster chain. CLUSTER must not be a bad + cluster. */ + +loff_t cluster_start(DOS_FS *fs,unsigned long cluster); + +/* Returns the byte offset of CLUSTER, relative to the respective device. */ + +void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner); + +/* Sets the owner pointer of the respective cluster to OWNER. If OWNER was NULL + before, it can be set to NULL or any non-NULL value. Otherwise, only NULL is + accepted as the new value. */ + +DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster); + +/* Returns the owner of the repective cluster or NULL if the cluster has no + owner. */ + +void fix_bad(DOS_FS *fs); + +/* Scans the disk for currently unused bad clusters and marks them as bad. */ + +void reclaim_free(DOS_FS *fs); + +/* Marks all allocated, but unused clusters as free. */ + +void reclaim_file(DOS_FS *fs); + +/* Scans the FAT for chains of allocated, but unused clusters and creates files + for them in the root directory. Also tries to fix all inconsistencies (e.g. + loops, shared clusters, etc.) in the process. */ + +unsigned long update_free(DOS_FS *fs); + +/* Updates free cluster count in FSINFO sector. */ + +#endif diff --git a/rosapps/sysutils/dosfsck/file.c b/rosapps/sysutils/dosfsck/file.c index ea5079cec45..9d6b4ff0c03 100644 --- a/rosapps/sysutils/dosfsck/file.c +++ b/rosapps/sysutils/dosfsck/file.c @@ -1,251 +1,251 @@ -/* file.c - Additional file attributes */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#include -#include -#include -#include -//#include - -#define _LINUX_STAT_H /* hack to avoid inclusion of */ -#define _LINUX_STRING_H_ /* hack to avoid inclusion of */ -#define _LINUX_FS_H /* hack to avoid inclusion of */ - -//#include -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -//# define __KERNEL__ -//# include -//# undef __KERNEL__ -//#endif - -#include "dosfsck.h" -#include "msdos_fs.h" - -#include "common.h" -#include "file.h" - - -FDSC *fp_root = NULL; - - -static void put_char(char **p,unsigned char c) -{ - if ((c >= ' ' && c < 0x7f) || c >= 0xa0) *(*p)++ = c; - else { - *(*p)++ = '\\'; - *(*p)++ = '0'+(c >> 6); - *(*p)++ = '0'+((c >> 3) & 7); - *(*p)++ = '0'+(c & 7); - } -} - - -char *file_name(unsigned char *fixed) -{ - static char path[MSDOS_NAME*4+2]; - char *p; - int i,j; - - p = path; - for (i = j = 0; i < 8; i++) - if (fixed[i] != ' ') { - while (j++ < i) *p++ = ' '; - put_char(&p,fixed[i]); - } - if (strncmp(fixed+8," ",3)) { - *p++ = '.'; - for (i = j = 0; i < 3; i++) - if (fixed[i+8] != ' ') { - while (j++ < i) *p++ = ' '; - put_char(&p,fixed[i+8]); - } - } - *p = 0; - return path; -} - - -int file_cvt(unsigned char *name,unsigned char *fixed) -{ - unsigned char c; - int size,ext,cnt; - - size = 8; - ext = 0; - while (*name) { - c = *name; - if (c < ' ' || c > 0x7e || strchr("*?<>|\"/",c)) { - printf("Invalid character in name. Use \\ooo for special " - "characters.\n"); - return 0; - } - if (c == '.') { - if (ext) { - printf("Duplicate dots in name.\n"); - return 0; - } - while (size--) *fixed++ = ' '; - size = 3; - ext = 1; - name++; - continue; - } - if (c == '\\') { - c = 0; - for (cnt = 3; cnt; cnt--) { - if (*name < '0' || *name > '7') { - printf("Invalid octal character.\n"); - return 0; - } - c = c*8+*name++-'0'; - } - if (cnt < 4) { - printf("Expected three octal digits.\n"); - return 0; - } - name += 3; - } - if (islower(c)) c = toupper(c); - if (size) { - *fixed++ = c; - size--; - } - name++; - } - if (*name || size == 8) return 0; - if (!ext) { - while (size--) *fixed++ = ' '; - size = 3; - } - while (size--) *fixed++ = ' '; - return 1; -} - - -void file_add(char *path,FD_TYPE type) -{ - FDSC **current,*walk; - char name[MSDOS_NAME]; - char *here; - - current = &fp_root; - if (*path != '/') die("%s: Absolute path required.",path); - path++; - while (1) { - if ((here = strchr(path,'/'))) *here = 0; - if (!file_cvt(path,name)) exit(2); - for (walk = *current; walk; walk = walk->next) - if (!here && (!strncmp(name,walk->name,MSDOS_NAME) || (type == - fdt_undelete && !strncmp(name+1,walk->name+1,MSDOS_NAME-1)))) - die("Ambiguous name: \"%s\"",path); - else if (here && !strncmp(name,walk->name,MSDOS_NAME)) break; - if (!walk) { - walk = alloc(sizeof(FDSC)); - strncpy(walk->name,name,MSDOS_NAME); - walk->type = here ? fdt_none : type; - walk->first = NULL; - walk->next = *current; - *current = walk; - } - current = &walk->first; - if (!here) break; - *here = '/'; - path = here+1; - } -} - - -FDSC **file_cd(FDSC **curr,char *fixed) -{ - FDSC **walk; - - if (!curr || !*curr) return NULL; - for (walk = curr; *walk; walk = &(*walk)->next) - if (!strncmp((*walk)->name,fixed,MSDOS_NAME) && (*walk)->first) - return &(*walk)->first; - return NULL; -} - - -static FDSC **file_find(FDSC **dir,char *fixed) -{ - if (!dir || !*dir) return NULL; - if (*(unsigned char *) fixed == DELETED_FLAG) { - while (*dir) { - if (!strncmp((*dir)->name+1,fixed+1,MSDOS_NAME-1) && !(*dir)->first) - return dir; - dir = &(*dir)->next; - } - return NULL; - } - while (*dir) { - if (!strncmp((*dir)->name,fixed,MSDOS_NAME) && !(*dir)->first) - return dir; - dir = &(*dir)->next; - } - return NULL; -} - - -FD_TYPE file_type(FDSC **curr,char *fixed) -{ - FDSC **this; - - if ((this = file_find(curr,fixed))) return (*this)->type; - return fdt_none; -} - - -void file_modify(FDSC **curr,char *fixed) -{ - FDSC **this,*next; - - if (!(this = file_find(curr,fixed))) - die("Internal error: file_find failed"); - switch ((*this)->type) { - case fdt_drop: - printf("Dropping %s\n",file_name(fixed)); - *(unsigned char *) fixed = DELETED_FLAG; - break; - case fdt_undelete: - *fixed = *(*this)->name; - printf("Undeleting %s\n",file_name(fixed)); - break; - default: - die("Internal error: file_modify"); - } - next = (*this)->next; - free(*this); - *this = next; -} - - -static void report_unused(FDSC *this) -{ - FDSC *next; - - while (this) { - next = this->next; - if (this->first) report_unused(this->first); - else if (this->type != fdt_none) - printf("Warning: did not %s file %s\n",this->type == fdt_drop ? - "drop" : "undelete",file_name(this->name)); - free(this); - this = next; - } -} - - -void file_unused(void) -{ - report_unused(fp_root); -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +/* file.c - Additional file attributes */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#include +#include +#include +#include +//#include + +#define _LINUX_STAT_H /* hack to avoid inclusion of */ +#define _LINUX_STRING_H_ /* hack to avoid inclusion of */ +#define _LINUX_FS_H /* hack to avoid inclusion of */ + +//#include +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +//# define __KERNEL__ +//# include +//# undef __KERNEL__ +//#endif + +#include "dosfsck.h" +#include "msdos_fs.h" + +#include "common.h" +#include "file.h" + + +FDSC *fp_root = NULL; + + +static void put_char(char **p,unsigned char c) +{ + if ((c >= ' ' && c < 0x7f) || c >= 0xa0) *(*p)++ = c; + else { + *(*p)++ = '\\'; + *(*p)++ = '0'+(c >> 6); + *(*p)++ = '0'+((c >> 3) & 7); + *(*p)++ = '0'+(c & 7); + } +} + + +char *file_name(unsigned char *fixed) +{ + static char path[MSDOS_NAME*4+2]; + char *p; + int i,j; + + p = path; + for (i = j = 0; i < 8; i++) + if (fixed[i] != ' ') { + while (j++ < i) *p++ = ' '; + put_char(&p,fixed[i]); + } + if (strncmp(fixed+8," ",3)) { + *p++ = '.'; + for (i = j = 0; i < 3; i++) + if (fixed[i+8] != ' ') { + while (j++ < i) *p++ = ' '; + put_char(&p,fixed[i+8]); + } + } + *p = 0; + return path; +} + + +int file_cvt(unsigned char *name,unsigned char *fixed) +{ + unsigned char c; + int size,ext,cnt; + + size = 8; + ext = 0; + while (*name) { + c = *name; + if (c < ' ' || c > 0x7e || strchr("*?<>|\"/",c)) { + printf("Invalid character in name. Use \\ooo for special " + "characters.\n"); + return 0; + } + if (c == '.') { + if (ext) { + printf("Duplicate dots in name.\n"); + return 0; + } + while (size--) *fixed++ = ' '; + size = 3; + ext = 1; + name++; + continue; + } + if (c == '\\') { + c = 0; + for (cnt = 3; cnt; cnt--) { + if (*name < '0' || *name > '7') { + printf("Invalid octal character.\n"); + return 0; + } + c = c*8+*name++-'0'; + } + if (cnt < 4) { + printf("Expected three octal digits.\n"); + return 0; + } + name += 3; + } + if (islower(c)) c = toupper(c); + if (size) { + *fixed++ = c; + size--; + } + name++; + } + if (*name || size == 8) return 0; + if (!ext) { + while (size--) *fixed++ = ' '; + size = 3; + } + while (size--) *fixed++ = ' '; + return 1; +} + + +void file_add(char *path,FD_TYPE type) +{ + FDSC **current,*walk; + char name[MSDOS_NAME]; + char *here; + + current = &fp_root; + if (*path != '/') die("%s: Absolute path required.",path); + path++; + while (1) { + if ((here = strchr(path,'/'))) *here = 0; + if (!file_cvt(path,name)) exit(2); + for (walk = *current; walk; walk = walk->next) + if (!here && (!strncmp(name,walk->name,MSDOS_NAME) || (type == + fdt_undelete && !strncmp(name+1,walk->name+1,MSDOS_NAME-1)))) + die("Ambiguous name: \"%s\"",path); + else if (here && !strncmp(name,walk->name,MSDOS_NAME)) break; + if (!walk) { + walk = alloc(sizeof(FDSC)); + strncpy(walk->name,name,MSDOS_NAME); + walk->type = here ? fdt_none : type; + walk->first = NULL; + walk->next = *current; + *current = walk; + } + current = &walk->first; + if (!here) break; + *here = '/'; + path = here+1; + } +} + + +FDSC **file_cd(FDSC **curr,char *fixed) +{ + FDSC **walk; + + if (!curr || !*curr) return NULL; + for (walk = curr; *walk; walk = &(*walk)->next) + if (!strncmp((*walk)->name,fixed,MSDOS_NAME) && (*walk)->first) + return &(*walk)->first; + return NULL; +} + + +static FDSC **file_find(FDSC **dir,char *fixed) +{ + if (!dir || !*dir) return NULL; + if (*(unsigned char *) fixed == DELETED_FLAG) { + while (*dir) { + if (!strncmp((*dir)->name+1,fixed+1,MSDOS_NAME-1) && !(*dir)->first) + return dir; + dir = &(*dir)->next; + } + return NULL; + } + while (*dir) { + if (!strncmp((*dir)->name,fixed,MSDOS_NAME) && !(*dir)->first) + return dir; + dir = &(*dir)->next; + } + return NULL; +} + + +FD_TYPE file_type(FDSC **curr,char *fixed) +{ + FDSC **this; + + if ((this = file_find(curr,fixed))) return (*this)->type; + return fdt_none; +} + + +void file_modify(FDSC **curr,char *fixed) +{ + FDSC **this,*next; + + if (!(this = file_find(curr,fixed))) + die("Internal error: file_find failed"); + switch ((*this)->type) { + case fdt_drop: + printf("Dropping %s\n",file_name(fixed)); + *(unsigned char *) fixed = DELETED_FLAG; + break; + case fdt_undelete: + *fixed = *(*this)->name; + printf("Undeleting %s\n",file_name(fixed)); + break; + default: + die("Internal error: file_modify"); + } + next = (*this)->next; + free(*this); + *this = next; +} + + +static void report_unused(FDSC *this) +{ + FDSC *next; + + while (this) { + next = this->next; + if (this->first) report_unused(this->first); + else if (this->type != fdt_none) + printf("Warning: did not %s file %s\n",this->type == fdt_drop ? + "drop" : "undelete",file_name(this->name)); + free(this); + this = next; + } +} + + +void file_unused(void) +{ + report_unused(fp_root); +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/file.h b/rosapps/sysutils/dosfsck/file.h index f9c3571aaf9..d7f1386801d 100644 --- a/rosapps/sysutils/dosfsck/file.h +++ b/rosapps/sysutils/dosfsck/file.h @@ -1,55 +1,55 @@ -/* file.h - Additional file attributes */ - -/* Written 1993 by Werner Almesberger */ - - -#ifndef _FILE_H -#define _FILE_H - -typedef enum { fdt_none,fdt_drop,fdt_undelete } FD_TYPE; - -typedef struct _fptr { - char name[MSDOS_NAME]; - FD_TYPE type; - struct _fptr *first; /* first entry */ - struct _fptr *next; /* next file in directory */ -} FDSC; - - -extern FDSC *fp_root; - - -char *file_name(unsigned char *fixed); - -/* Returns a pointer to a pretty-printed representation of a fixed MS-DOS file - name. */ - -int file_cvt(unsigned char *name,unsigned char *fixed); - -/* Converts a pretty-printed file name to the fixed MS-DOS format. Returns a - non-zero integer on success, zero on failure. */ - -void file_add(char *path,FD_TYPE type); - -/* Define special attributes for a path. TYPE can be either FDT_DROP or - FDT_UNDELETE. */ - -FDSC **file_cd(FDSC **curr,char *fixed); - -/* Returns a pointer to the directory descriptor of the subdirectory FIXED of - CURR, or NULL if no such subdirectory exists. */ - -FD_TYPE file_type(FDSC **curr,char *fixed); - -/* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no - such file exists or if CURR is NULL. */ - -void file_modify(FDSC **curr,char *fixed); - -/* Performs the necessary operation on the entry of CURR that is named FIXED. */ - -void file_unused(void); - -/* Displays warnings for all unused file attributes. */ - -#endif +/* file.h - Additional file attributes */ + +/* Written 1993 by Werner Almesberger */ + + +#ifndef _FILE_H +#define _FILE_H + +typedef enum { fdt_none,fdt_drop,fdt_undelete } FD_TYPE; + +typedef struct _fptr { + char name[MSDOS_NAME]; + FD_TYPE type; + struct _fptr *first; /* first entry */ + struct _fptr *next; /* next file in directory */ +} FDSC; + + +extern FDSC *fp_root; + + +char *file_name(unsigned char *fixed); + +/* Returns a pointer to a pretty-printed representation of a fixed MS-DOS file + name. */ + +int file_cvt(unsigned char *name,unsigned char *fixed); + +/* Converts a pretty-printed file name to the fixed MS-DOS format. Returns a + non-zero integer on success, zero on failure. */ + +void file_add(char *path,FD_TYPE type); + +/* Define special attributes for a path. TYPE can be either FDT_DROP or + FDT_UNDELETE. */ + +FDSC **file_cd(FDSC **curr,char *fixed); + +/* Returns a pointer to the directory descriptor of the subdirectory FIXED of + CURR, or NULL if no such subdirectory exists. */ + +FD_TYPE file_type(FDSC **curr,char *fixed); + +/* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no + such file exists or if CURR is NULL. */ + +void file_modify(FDSC **curr,char *fixed); + +/* Performs the necessary operation on the entry of CURR that is named FIXED. */ + +void file_unused(void); + +/* Displays warnings for all unused file attributes. */ + +#endif diff --git a/rosapps/sysutils/dosfsck/io.c b/rosapps/sysutils/dosfsck/io.c index 32aee9f3218..b089b00fc93 100644 --- a/rosapps/sysutils/dosfsck/io.c +++ b/rosapps/sysutils/dosfsck/io.c @@ -1,423 +1,423 @@ -/* io.c - Virtual disk input/output */ - -/* Written 1993 by Werner Almesberger */ - -/* - * Thu Feb 26 01:15:36 CET 1998: Martin Schulze - * Fixed nasty bug that caused every file with a name like - * xxxxxxxx.xxx to be treated as bad name that needed to be fixed. - */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - -#include -#include -#include -//#include -#include -//#include -#include -#include -#include -//#include - - -#ifdef _WIN32 -#define _WIN32_WINNT 0x0400 -#include -#include -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#define __BYTE_ORDER __LITTLE_ENDIAN -#define inline -#define __attribute__(x) -#define BLOCK_SIZE 512 -#endif - - -#include "dosfsck.h" -#include "common.h" -#include "io.h" - - -typedef struct _change { - void *data; - loff_t pos; - int size; - struct _change *next; -} CHANGE; - - -static CHANGE *changes,*last; -static int fd,did_change = 0; - -unsigned device_no; - -static int WIN32open(const char *path, int oflag, ...); -#define open WIN32open -static int WIN32close(int fd); -#define close WIN32close -static int WIN32read(int fd, void *buf, unsigned int len); -#define read WIN32read -static int WIN32write(int fd, void *buf, unsigned int len); -#define write WIN32write -static loff_t WIN32llseek(int fd, loff_t offset, int whence); -#ifdef llseek -#undef llseek -#endif -#define llseek WIN32llseek - -static int is_device = 0; - -void fs_open(char *path,int rw) -{ -#ifdef _WIN32 - static char dev_buf[] = "\\\\.\\X:"; -#else - struct stat stbuf; -#endif - - if (path[1] == ':' && path[2] == '\0') { - dev_buf[4] = path[0]; - path = dev_buf; -// is_device = 1; - } - - if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0) - pdie("open %s",path); - changes = last = NULL; - did_change = 0; - -#if 0 - if (fstat(fd,&stbuf) < 0) - pdie("fstat %s",path); - device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0; -#endif -} - - -void fs_read(loff_t pos,int size,void *data) -{ - CHANGE *walk; - int got; -#if 1 // TMN - const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN: - const loff_t seekpos_aligned = pos - (pos % 512); // TMN: - const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN: - const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN: - char* tmpBuf = malloc(readsize_aligned); // TMN: -#ifdef _MSC_VER - if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %I64d",pos); - if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %I64dd",size,pos); -#else - if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos); - if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %lld",size,pos); -#endif - assert(got >= size); - got = size; - assert(seek_delta + size <= readsize); - memcpy(data, tmpBuf+seek_delta, size); - free(tmpBuf); -#else // TMN: - if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); - if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos); -#endif // TMN: - if (got != size) die("Got %d bytes instead of %d at %lld",got,size,pos); - for (walk = changes; walk; walk = walk->next) { - if (walk->pos < pos+size && walk->pos+walk->size > pos) { - if (walk->pos < pos) - memcpy(data,(char *) walk->data+pos-walk->pos,min((size_t)size, - (size_t)(walk->size-pos+walk->pos))); - else memcpy((char *) data+walk->pos-pos,walk->data,min((size_t)walk->size, - (size_t)(size+pos-walk->pos))); - } - } -} - - -int fs_test(loff_t pos,int size) -{ - void *scratch; - int okay; - -#if 1 // TMN - const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN: - const loff_t seekpos_aligned = pos - (pos % 512); // TMN: - const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN: - const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN: - scratch = alloc(readsize_aligned); - if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos); - okay = read(fd,scratch,readsize_aligned) == (int)readsize_aligned; - free(scratch); -#else // TMN: - if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); - scratch = alloc(size); - okay = read(fd,scratch,size) == size; - free(scratch); -#endif // TMN: - return okay; -} - - -void fs_write(loff_t pos,int size,void *data) -{ - CHANGE *new; - int did; +/* io.c - Virtual disk input/output */ + +/* Written 1993 by Werner Almesberger */ + +/* + * Thu Feb 26 01:15:36 CET 1998: Martin Schulze + * Fixed nasty bug that caused every file with a name like + * xxxxxxxx.xxx to be treated as bad name that needed to be fixed. + */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + +#include +#include +#include +//#include +#include +//#include +#include +#include +#include +//#include + + +#ifdef _WIN32 +#define _WIN32_WINNT 0x0400 +#include +#include +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __BYTE_ORDER __LITTLE_ENDIAN +#define inline +#define __attribute__(x) +#define BLOCK_SIZE 512 +#endif + + +#include "dosfsck.h" +#include "common.h" +#include "io.h" + + +typedef struct _change { + void *data; + loff_t pos; + int size; + struct _change *next; +} CHANGE; + + +static CHANGE *changes,*last; +static int fd,did_change = 0; + +unsigned device_no; + +static int WIN32open(const char *path, int oflag, ...); +#define open WIN32open +static int WIN32close(int fd); +#define close WIN32close +static int WIN32read(int fd, void *buf, unsigned int len); +#define read WIN32read +static int WIN32write(int fd, void *buf, unsigned int len); +#define write WIN32write +static loff_t WIN32llseek(int fd, loff_t offset, int whence); +#ifdef llseek +#undef llseek +#endif +#define llseek WIN32llseek + +static int is_device = 0; + +void fs_open(char *path,int rw) +{ +#ifdef _WIN32 + static char dev_buf[] = "\\\\.\\X:"; +#else + struct stat stbuf; +#endif + + if (path[1] == ':' && path[2] == '\0') { + dev_buf[4] = path[0]; + path = dev_buf; +// is_device = 1; + } + + if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0) + pdie("open %s",path); + changes = last = NULL; + did_change = 0; + +#if 0 + if (fstat(fd,&stbuf) < 0) + pdie("fstat %s",path); + device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0; +#endif +} + + +void fs_read(loff_t pos,int size,void *data) +{ + CHANGE *walk; + int got; +#if 1 // TMN + const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN: + const loff_t seekpos_aligned = pos - (pos % 512); // TMN: + const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN: + const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN: + char* tmpBuf = malloc(readsize_aligned); // TMN: +#ifdef _MSC_VER + if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %I64d",pos); + if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %I64dd",size,pos); +#else + if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos); + if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %lld",size,pos); +#endif + assert(got >= size); + got = size; + assert(seek_delta + size <= readsize); + memcpy(data, tmpBuf+seek_delta, size); + free(tmpBuf); +#else // TMN: + if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); + if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos); +#endif // TMN: + if (got != size) die("Got %d bytes instead of %d at %lld",got,size,pos); + for (walk = changes; walk; walk = walk->next) { + if (walk->pos < pos+size && walk->pos+walk->size > pos) { + if (walk->pos < pos) + memcpy(data,(char *) walk->data+pos-walk->pos,min((size_t)size, + (size_t)(walk->size-pos+walk->pos))); + else memcpy((char *) data+walk->pos-pos,walk->data,min((size_t)walk->size, + (size_t)(size+pos-walk->pos))); + } + } +} + + +int fs_test(loff_t pos,int size) +{ + void *scratch; + int okay; + +#if 1 // TMN + const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN: + const loff_t seekpos_aligned = pos - (pos % 512); // TMN: + const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN: + const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN: + scratch = alloc(readsize_aligned); + if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos); + okay = read(fd,scratch,readsize_aligned) == (int)readsize_aligned; + free(scratch); +#else // TMN: + if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); + scratch = alloc(size); + okay = read(fd,scratch,size) == size; + free(scratch); +#endif // TMN: + return okay; +} + + +void fs_write(loff_t pos,int size,void *data) +{ + CHANGE *new; + int did; #if 1 //SAE void *scratch; - const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; - const loff_t seekpos_aligned = pos - (pos % 512); - const size_t seek_delta = (size_t)(pos - seekpos_aligned); - const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; + const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; + const loff_t seekpos_aligned = pos - (pos % 512); + const size_t seek_delta = (size_t)(pos - seekpos_aligned); + const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; scratch = alloc(readsize_aligned); - if (write_immed) { - did_change = 1; - if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos); + if (write_immed) { + did_change = 1; + if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos); if ((did = write(fd,data,readsize_aligned)) == (int)readsize_aligned) { free(scratch); return; - } - if (did < 0) pdie("Write %d bytes at %lld",size,pos); - die("Wrote %d bytes instead of %d at %lld",did,size,pos); - } - new = alloc(sizeof(CHANGE)); - new->pos = pos; - memcpy(new->data = alloc(new->size = size),data,size); - new->next = NULL; - if (last) last->next = new; - else changes = new; + } + if (did < 0) pdie("Write %d bytes at %lld",size,pos); + die("Wrote %d bytes instead of %d at %lld",did,size,pos); + } + new = alloc(sizeof(CHANGE)); + new->pos = pos; + memcpy(new->data = alloc(new->size = size),data,size); + new->next = NULL; + if (last) last->next = new; + else changes = new; last = new; -#else //SAE - if (write_immed) { - did_change = 1; - if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); - if ((did = write(fd,data,size)) == size) return; - if (did < 0) pdie("Write %d bytes at %lld",size,pos); - die("Wrote %d bytes instead of %d at %lld",did,size,pos); - } - new = alloc(sizeof(CHANGE)); - new->pos = pos; - memcpy(new->data = alloc(new->size = size),data,size); - new->next = NULL; - if (last) last->next = new; - else changes = new; +#else //SAE + if (write_immed) { + did_change = 1; + if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); + if ((did = write(fd,data,size)) == size) return; + if (did < 0) pdie("Write %d bytes at %lld",size,pos); + die("Wrote %d bytes instead of %d at %lld",did,size,pos); + } + new = alloc(sizeof(CHANGE)); + new->pos = pos; + memcpy(new->data = alloc(new->size = size),data,size); + new->next = NULL; + if (last) last->next = new; + else changes = new; last = new; -#endif //SAE -} - - -static void fs_flush(void) -{ - CHANGE *this; - int size; - - while (changes) { - this = changes; - changes = changes->next; - if (llseek(fd,this->pos,0) != this->pos) - fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n", - (__int64)this->pos,strerror(errno),this->size); - else if ((size = write(fd,this->data,this->size)) < 0) - fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size, - (__int64)this->pos,strerror(errno)); - else if (size != this->size) - fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld." - "\n",size,this->size,(__int64)this->pos); - free(this->data); - free(this); - } -} - - -int fs_close(int write) -{ - CHANGE *next; - int changed; - - changed = !!changes; - if (write) fs_flush(); - else while (changes) { - next = changes->next; - free(changes->data); - free(changes); - changes = next; - } - if (close(fd) < 0) pdie("closing file system"); - return changed || did_change; -} - - -int fs_changed(void) -{ - return !!changes || did_change; -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ - - -#define O_SHORT_LIVED _O_SHORT_LIVED -//#define O_ACCMODE 3 -#define O_NONE 3 -#define O_BACKUP 0x10000 -#define O_SHARED 0x20000 - -static int WIN32open(const char *path, int oflag, ...) -{ - HANDLE fh; - DWORD desiredAccess; - DWORD shareMode; - DWORD creationDisposition; - DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL; - SECURITY_ATTRIBUTES securityAttributes; - va_list ap; - int pmode; - int trunc = FALSE; - - securityAttributes.nLength = sizeof(securityAttributes); - securityAttributes.lpSecurityDescriptor = NULL; - securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE; - switch (oflag & O_ACCMODE) { - case O_RDONLY: - desiredAccess = GENERIC_READ; -// shareMode = FILE_SHARE_READ; - shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; // TMN: - break; - case O_WRONLY: - desiredAccess = GENERIC_WRITE; - shareMode = 0; - break; - case O_RDWR: - desiredAccess = GENERIC_READ|GENERIC_WRITE; - shareMode = 0; - break; - case O_NONE: - desiredAccess = 0; - shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; - } - if (oflag & O_APPEND) { - desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE; - shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; - } - if (oflag & O_SHARED) - shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE; - switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) { - case 0: - case O_EXCL: - creationDisposition = OPEN_EXISTING; - break; - case O_CREAT: - creationDisposition = OPEN_ALWAYS; - break; - case O_CREAT|O_EXCL: - case O_CREAT|O_TRUNC|O_EXCL: - creationDisposition = CREATE_NEW; - break; - case O_TRUNC: - case O_TRUNC|O_EXCL: - creationDisposition = TRUNCATE_EXISTING; - break; - case O_CREAT|O_TRUNC: - creationDisposition = OPEN_ALWAYS; - trunc = TRUE; - break; - } - if (oflag & O_CREAT) { - va_start(ap, oflag); - pmode = va_arg(ap, int); - va_end(ap); - if ((pmode & 0222) == 0) - flagsAttributes |= FILE_ATTRIBUTE_READONLY; - } - if (oflag & O_TEMPORARY) { - flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE; - desiredAccess |= DELETE; - } - if (oflag & O_SHORT_LIVED) - flagsAttributes |= FILE_ATTRIBUTE_TEMPORARY; - if (oflag & O_SEQUENTIAL) - flagsAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; - else if (oflag & O_RANDOM) - flagsAttributes |= FILE_FLAG_RANDOM_ACCESS; - if (oflag & O_BACKUP) - flagsAttributes |= FILE_FLAG_BACKUP_SEMANTICS; - if ((fh = CreateFile(path, desiredAccess, shareMode, &securityAttributes, - creationDisposition, flagsAttributes, NULL)) == INVALID_HANDLE_VALUE) { - errno = GetLastError(); - return -1; - } - if (trunc) { - if (!SetEndOfFile(fh)) { - errno = GetLastError(); - CloseHandle(fh); - DeleteFile(path); - return -1; - } - } - return (int)fh; -} - -static int WIN32close(int fd) -{ - if (!CloseHandle((HANDLE)fd)) { - errno = GetLastError(); - return -1; - } - return 0; -} - -static int WIN32read(int fd, void *buf, unsigned int len) -{ - DWORD actualLen; - - if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) { - errno = GetLastError(); - if (errno == ERROR_BROKEN_PIPE) - return 0; - else - return -1; - } - return (int)actualLen; -} - -static int WIN32write(int fd, void *buf, unsigned int len) -{ - DWORD actualLen; - - if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) { - errno = GetLastError(); - return -1; - } - return (int)actualLen; -} - -static loff_t WIN32llseek(int fd, loff_t offset, int whence) -{ - long lo, hi; - DWORD err; - - lo = (long)(offset & 0xffffffff); - hi = (long)(offset >> 32); - lo = SetFilePointer((HANDLE)fd, lo, &hi, whence); - if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) { - errno = err; - return -1; - } - return ((loff_t)hi << 32) | (__u32)lo; -} - -int fsctl(int fd, int code) -{ - DWORD ret; - if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) { - errno = GetLastError(); - return -1; - } - return 0; -} +#endif //SAE +} + + +static void fs_flush(void) +{ + CHANGE *this; + int size; + + while (changes) { + this = changes; + changes = changes->next; + if (llseek(fd,this->pos,0) != this->pos) + fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n", + (__int64)this->pos,strerror(errno),this->size); + else if ((size = write(fd,this->data,this->size)) < 0) + fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size, + (__int64)this->pos,strerror(errno)); + else if (size != this->size) + fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld." + "\n",size,this->size,(__int64)this->pos); + free(this->data); + free(this); + } +} + + +int fs_close(int write) +{ + CHANGE *next; + int changed; + + changed = !!changes; + if (write) fs_flush(); + else while (changes) { + next = changes->next; + free(changes->data); + free(changes); + changes = next; + } + if (close(fd) < 0) pdie("closing file system"); + return changed || did_change; +} + + +int fs_changed(void) +{ + return !!changes || did_change; +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ + + +#define O_SHORT_LIVED _O_SHORT_LIVED +//#define O_ACCMODE 3 +#define O_NONE 3 +#define O_BACKUP 0x10000 +#define O_SHARED 0x20000 + +static int WIN32open(const char *path, int oflag, ...) +{ + HANDLE fh; + DWORD desiredAccess; + DWORD shareMode; + DWORD creationDisposition; + DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL; + SECURITY_ATTRIBUTES securityAttributes; + va_list ap; + int pmode; + int trunc = FALSE; + + securityAttributes.nLength = sizeof(securityAttributes); + securityAttributes.lpSecurityDescriptor = NULL; + securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE; + switch (oflag & O_ACCMODE) { + case O_RDONLY: + desiredAccess = GENERIC_READ; +// shareMode = FILE_SHARE_READ; + shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; // TMN: + break; + case O_WRONLY: + desiredAccess = GENERIC_WRITE; + shareMode = 0; + break; + case O_RDWR: + desiredAccess = GENERIC_READ|GENERIC_WRITE; + shareMode = 0; + break; + case O_NONE: + desiredAccess = 0; + shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; + } + if (oflag & O_APPEND) { + desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE; + shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; + } + if (oflag & O_SHARED) + shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE; + switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) { + case 0: + case O_EXCL: + creationDisposition = OPEN_EXISTING; + break; + case O_CREAT: + creationDisposition = OPEN_ALWAYS; + break; + case O_CREAT|O_EXCL: + case O_CREAT|O_TRUNC|O_EXCL: + creationDisposition = CREATE_NEW; + break; + case O_TRUNC: + case O_TRUNC|O_EXCL: + creationDisposition = TRUNCATE_EXISTING; + break; + case O_CREAT|O_TRUNC: + creationDisposition = OPEN_ALWAYS; + trunc = TRUE; + break; + } + if (oflag & O_CREAT) { + va_start(ap, oflag); + pmode = va_arg(ap, int); + va_end(ap); + if ((pmode & 0222) == 0) + flagsAttributes |= FILE_ATTRIBUTE_READONLY; + } + if (oflag & O_TEMPORARY) { + flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + desiredAccess |= DELETE; + } + if (oflag & O_SHORT_LIVED) + flagsAttributes |= FILE_ATTRIBUTE_TEMPORARY; + if (oflag & O_SEQUENTIAL) + flagsAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; + else if (oflag & O_RANDOM) + flagsAttributes |= FILE_FLAG_RANDOM_ACCESS; + if (oflag & O_BACKUP) + flagsAttributes |= FILE_FLAG_BACKUP_SEMANTICS; + if ((fh = CreateFile(path, desiredAccess, shareMode, &securityAttributes, + creationDisposition, flagsAttributes, NULL)) == INVALID_HANDLE_VALUE) { + errno = GetLastError(); + return -1; + } + if (trunc) { + if (!SetEndOfFile(fh)) { + errno = GetLastError(); + CloseHandle(fh); + DeleteFile(path); + return -1; + } + } + return (int)fh; +} + +static int WIN32close(int fd) +{ + if (!CloseHandle((HANDLE)fd)) { + errno = GetLastError(); + return -1; + } + return 0; +} + +static int WIN32read(int fd, void *buf, unsigned int len) +{ + DWORD actualLen; + + if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) { + errno = GetLastError(); + if (errno == ERROR_BROKEN_PIPE) + return 0; + else + return -1; + } + return (int)actualLen; +} + +static int WIN32write(int fd, void *buf, unsigned int len) +{ + DWORD actualLen; + + if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) { + errno = GetLastError(); + return -1; + } + return (int)actualLen; +} + +static loff_t WIN32llseek(int fd, loff_t offset, int whence) +{ + long lo, hi; + DWORD err; + + lo = (long)(offset & 0xffffffff); + hi = (long)(offset >> 32); + lo = SetFilePointer((HANDLE)fd, lo, &hi, whence); + if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) { + errno = err; + return -1; + } + return ((loff_t)hi << 32) | (__u32)lo; +} + +int fsctl(int fd, int code) +{ + DWORD ret; + if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) { + errno = GetLastError(); + return -1; + } + return 0; +} diff --git a/rosapps/sysutils/dosfsck/io.h b/rosapps/sysutils/dosfsck/io.h index a9cc75dfc45..cdf3c586ec8 100644 --- a/rosapps/sysutils/dosfsck/io.h +++ b/rosapps/sysutils/dosfsck/io.h @@ -1,54 +1,54 @@ -/* io.h - Virtual disk input/output */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#ifndef _IO_H -#define _IO_H - -//#include /* for loff_t */ -#include "dosfsck.h" - -/* In earlier versions, an own llseek() was used, but glibc lseek() is - * sufficient (or even better :) for 64 bit offsets in the meantime */ -#define llseek lseek - -void fs_open(char *path,int rw); - -/* Opens the file system PATH. If RW is zero, the file system is opened - read-only, otherwise, it is opened read-write. */ - -void fs_read(loff_t pos,int size,void *data); - -/* Reads SIZE bytes starting at POS into DATA. Performs all applicable - changes. */ - -int fs_test(loff_t pos,int size); - -/* Returns a non-zero integer if SIZE bytes starting at POS can be read without - errors. Otherwise, it returns zero. */ - -void fs_write(loff_t pos,int size,void *data); - -/* If write_immed is non-zero, SIZE bytes are written from DATA to the disk, - starting at POS. If write_immed is zero, the change is added to a list in - memory. */ - -int fs_close(int write); - -/* Closes the file system, performs all pending changes if WRITE is non-zero - and removes the list of changes. Returns a non-zero integer if the file - system has been changed since the last fs_open, zero otherwise. */ - -int fs_changed(void); - -/* Determines whether the file system has changed. See fs_close. */ - -extern unsigned device_no; - -/* Major number of device (0 if file) and size (in 512 byte sectors) */ - -#endif +/* io.h - Virtual disk input/output */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#ifndef _IO_H +#define _IO_H + +//#include /* for loff_t */ +#include "dosfsck.h" + +/* In earlier versions, an own llseek() was used, but glibc lseek() is + * sufficient (or even better :) for 64 bit offsets in the meantime */ +#define llseek lseek + +void fs_open(char *path,int rw); + +/* Opens the file system PATH. If RW is zero, the file system is opened + read-only, otherwise, it is opened read-write. */ + +void fs_read(loff_t pos,int size,void *data); + +/* Reads SIZE bytes starting at POS into DATA. Performs all applicable + changes. */ + +int fs_test(loff_t pos,int size); + +/* Returns a non-zero integer if SIZE bytes starting at POS can be read without + errors. Otherwise, it returns zero. */ + +void fs_write(loff_t pos,int size,void *data); + +/* If write_immed is non-zero, SIZE bytes are written from DATA to the disk, + starting at POS. If write_immed is zero, the change is added to a list in + memory. */ + +int fs_close(int write); + +/* Closes the file system, performs all pending changes if WRITE is non-zero + and removes the list of changes. Returns a non-zero integer if the file + system has been changed since the last fs_open, zero otherwise. */ + +int fs_changed(void); + +/* Determines whether the file system has changed. See fs_close. */ + +extern unsigned device_no; + +/* Major number of device (0 if file) and size (in 512 byte sectors) */ + +#endif diff --git a/rosapps/sysutils/dosfsck/lfn.c b/rosapps/sysutils/dosfsck/lfn.c index 1af73edacdb..3cd23e3bc3f 100644 --- a/rosapps/sysutils/dosfsck/lfn.c +++ b/rosapps/sysutils/dosfsck/lfn.c @@ -1,480 +1,480 @@ -/* lfn.c - Functions for handling VFAT long filenames */ - -/* Written 1998 by Roman Hodek */ - -#include -#include -#include -#include -#include - -#include "common.h" -#include "io.h" -#include "dosfsck.h" -#include "lfn.h" -#include "file.h" - -typedef struct { - __u8 id; /* sequence number for slot */ - __u8 name0_4[10]; /* first 5 characters in name */ - __u8 attr; /* attribute byte */ - __u8 reserved; /* always 0 */ - __u8 alias_checksum; /* checksum for 8.3 alias */ - __u8 name5_10[12]; /* 6 more characters in name */ - __u16 start; /* starting cluster number, 0 in long slots */ - __u8 name11_12[4]; /* last 2 characters in name */ -} LFN_ENT; - -#define LFN_ID_START 0x40 -#define LFN_ID_SLOTMASK 0x1f - -#define CHARS_PER_LFN 13 - -/* These modul-global vars represent the state of the LFN parser */ -unsigned char *lfn_unicode = NULL; -unsigned char lfn_checksum; -int lfn_slot = -1; -loff_t *lfn_offsets = NULL; -int lfn_parts = 0; - -static unsigned char fat_uni2esc[64] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', - 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', - 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', - 'u', 'v', 'w', 'x', 'y', 'z', '+', '-' -}; - -/* This defines which unicode chars are directly convertable to ISO-8859-1 */ -#define UNICODE_CONVERTABLE(cl,ch) (ch == 0 && (cl < 0x80 || cl >= 0xa0)) - -/* for maxlen param */ -#define UNTIL_0 INT_MAX - -static void copy_lfn_part( char *dst, LFN_ENT *lfn ); -static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q ); - -/* Convert name part in 'lfn' from unicode to ASCII */ -static __inline char* CNV_THIS_PART(LFN_ENT *lfn) -{ \ - char __part_uni[CHARS_PER_LFN*2]; - copy_lfn_part( __part_uni, lfn ); - cnv_unicode( __part_uni, CHARS_PER_LFN, 0 ); -} - -/* Convert name parts collected so far (from previous slots) from unicode to - * ASCII */ -#define CNV_PARTS_SO_FAR() \ - (cnv_unicode( lfn_unicode+(lfn_slot*CHARS_PER_LFN*2), \ - lfn_parts*CHARS_PER_LFN, 0 )) - -/* This function converts an unicode string to a normal ASCII string, assuming - * ISO-8859-1 charset. Characters not in 8859-1 are converted to the same - * escape notation as used by the kernel, i.e. the uuencode-like ":xxx" */ -static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q ) -{ - const unsigned char *up; - unsigned char *out, *cp; - int len, val; - - for( len = 0, up = uni; (up-uni)/2 < maxlen && (up[0] || up[1]); up += 2 ){ - if (UNICODE_CONVERTABLE(up[0],up[1])) - ++len; - else - len += 4; - } - cp = out = use_q ? qalloc( &mem_queue, len+1 ) : alloc( len+1 ); - - for( up = uni; (up-uni)/2 < maxlen && (up[0] || up[1]); up += 2 ) { - if (UNICODE_CONVERTABLE(up[0],up[1])) - *cp++ = up[0]; - else { - /* here the same escape notation is used as in the Linux kernel */ - *cp++ = ':'; - val = (up[1] << 8) + up[0]; - cp[2] = fat_uni2esc[val & 0x3f]; - val >>= 6; - cp[1] = fat_uni2esc[val & 0x3f]; - val >>= 6; - cp[0] = fat_uni2esc[val & 0x3f]; - cp += 3; - } - } - *cp = 0; - - return( out ); -} - - -static void copy_lfn_part( char *dst, LFN_ENT *lfn ) -{ - memcpy( dst, lfn->name0_4, 10 ); - memcpy( dst+10, lfn->name5_10, 12 ); - memcpy( dst+22, lfn->name11_12, 4 ); -} - - -static void clear_lfn_slots( int start, int end ) -{ - int i; - LFN_ENT empty; - - /* New dir entry is zeroed except first byte, which is set to 0xe5. - * This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading - * a directory at the first zero entry... - */ - memset( &empty, 0, sizeof(empty) ); - empty.id = DELETED_FLAG; - - for( i = start; i <= end; ++i ) { - fs_write( lfn_offsets[i], sizeof(LFN_ENT), &empty ); - } -} - -void lfn_reset( void ) -{ - if (lfn_unicode) - free( lfn_unicode ); - lfn_unicode = NULL; - if (lfn_offsets) - free( lfn_offsets ); - lfn_offsets = NULL; - lfn_slot = -1; -} - - -/* This function is only called with de->attr == VFAT_LN_ATTR. It stores part - * of the long name. */ -void lfn_add_slot( DIR_ENT *de, loff_t dir_offset ) -{ - LFN_ENT *lfn = (LFN_ENT *)de; - unsigned offset; - - if (de->attr != VFAT_LN_ATTR) - die("lfn_add_slot called with non-LFN directory entry"); - - if (lfn->id & LFN_ID_START) { - if (lfn_slot != -1) { - int can_clear = 0; - /* There is already a LFN "in progess", so it is an error that a - * new start entry is here. */ - /* Causes: 1) if slot# == expected: start bit set mysteriously, 2) - * old LFN overwritten by new one */ - /* Fixes: 1) delete previous LFN 2) if slot# == expected and - * checksum ok: clear start bit */ - /* XXX: Should delay that until next LFN known (then can better - * display the name) */ - printf( "A new long file name starts within an old one.\n" ); - if ((lfn->id & LFN_ID_SLOTMASK) == lfn_slot && - lfn->alias_checksum == lfn_checksum) { - char *part1 = CNV_THIS_PART(lfn); - char *part2 = CNV_PARTS_SO_FAR(); - printf( " It could be that the LFN start bit is wrong here\n" - " if \"%s\" seems to match \"%s\".\n", part1, part2 ); - free( part1 ); - free( part2 ); - can_clear = 1; - } - if (interactive) { - printf( "1: Delete previous LFN\n2: Leave it as it is.\n" ); - if (can_clear) - printf( "3: Clear start bit and concatenate LFNs\n" ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( can_clear ? "123" : "12", "?" )) { - case '1': - clear_lfn_slots( 0, lfn_parts-1 ); - lfn_reset(); - break; - case '2': - break; - case '3': - lfn->id &= ~LFN_ID_START; - fs_write( dir_offset+offsetof(LFN_ENT,id), - sizeof(lfn->id), &lfn->id ); - break; - } - } - } - lfn_slot = lfn->id & LFN_ID_SLOTMASK; - lfn_checksum = lfn->alias_checksum; - lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 ); - lfn_offsets = alloc( lfn_slot*sizeof(loff_t) ); - lfn_parts = 0; - } - else if (lfn_slot == -1) { - /* No LFN in progress, but slot found; start bit missing */ - /* Causes: 1) start bit got lost, 2) Previous slot with start bit got - * lost */ - /* Fixes: 1) delete LFN, 2) set start bit */ - char *part = CNV_THIS_PART(lfn); - printf( "Long filename fragment \"%s\" found outside a LFN " - "sequence.\n (Maybe the start bit is missing on the " - "last fragment)\n", part ); - if (interactive) { - printf( "1: Delete fragment\n2: Leave it as it is.\n" - "3: Set start bit\n" ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( "123", "?" )) { - case '1': - if (!lfn_offsets) - lfn_offsets = alloc( sizeof(loff_t) ); - lfn_offsets[0] = dir_offset; - clear_lfn_slots( 0, 0 ); - lfn_reset(); - return; - case '2': - lfn_reset(); - return; - case '3': - lfn->id |= LFN_ID_START; - fs_write( dir_offset+offsetof(LFN_ENT,id), - sizeof(lfn->id), &lfn->id ); - lfn_slot = lfn->id & LFN_ID_SLOTMASK; - lfn_checksum = lfn->alias_checksum; - lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 ); - lfn_offsets = alloc( lfn_slot*sizeof(loff_t) ); - lfn_parts = 0; - break; - } - } - } - else if ((lfn->id & LFN_ID_SLOTMASK) != lfn_slot) { - /* wrong sequence number */ - /* Causes: 1) seq-no destroyed */ - /* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts - * are ok?, maybe only if checksum is ok?) (Attention: space - * for name was allocated before!) */ - int can_fix = 0; - printf( "Unexpected long filename sequence number " - "(%d vs. expected %d).\n", - (lfn->id & LFN_ID_SLOTMASK), lfn_slot ); - if (lfn->alias_checksum == lfn_checksum) { - char *part1 = CNV_THIS_PART(lfn); - char *part2 = CNV_PARTS_SO_FAR(); - printf( " It could be that just the number is wrong\n" - " if \"%s\" seems to match \"%s\".\n", part1, part2 ); - free( part1 ); - free( part2 ); - can_fix = 1; - } - if (interactive) { - printf( "1: Delete LFN\n2: Leave it as it is (and ignore LFN so far)\n" ); - if (can_fix) - printf( "3: Correct sequence number\n" ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( can_fix ? "123" : "12", "?" )) { - case '1': - lfn_offsets[lfn_parts++] = dir_offset; - clear_lfn_slots( 0, lfn_parts-1 ); - lfn_reset(); - return; - case '2': - lfn_reset(); - return; - case '3': - lfn->id = (lfn->id & ~LFN_ID_SLOTMASK) | lfn_slot; - fs_write( dir_offset+offsetof(LFN_ENT,id), - sizeof(lfn->id), &lfn->id ); - break; - } - } - } - - if (lfn->alias_checksum != lfn_checksum) { - /* checksum mismatch */ - /* Causes: 1) checksum field here destroyed */ - /* Fixes: 1) delete LFN, 2) fix checksum */ - printf( "Checksum in long filename part wrong " - "(%02x vs. expected %02x).\n", - lfn->alias_checksum, lfn_checksum ); - if (interactive) { - printf( "1: Delete LFN\n2: Leave it as it is.\n" - "3: Correct checksum\n" ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( "123", "?" )) { - case '1': - lfn_offsets[lfn_parts++] = dir_offset; - clear_lfn_slots( 0, lfn_parts-1 ); - lfn_reset(); - return; - case '2': - break; - case '3': - lfn->alias_checksum = lfn_checksum; - fs_write( dir_offset+offsetof(LFN_ENT,alias_checksum), - sizeof(lfn->alias_checksum), &lfn->alias_checksum ); - break; - } - } - } - - if (lfn_slot != -1) { - lfn_slot--; - offset = lfn_slot * CHARS_PER_LFN*2; - copy_lfn_part( lfn_unicode+offset, lfn ); - if (lfn->id & LFN_ID_START) - lfn_unicode[offset+26] = lfn_unicode[offset+27] = 0; - lfn_offsets[lfn_parts++] = dir_offset; - } - - if (lfn->reserved != 0) { - printf( "Reserved field in VFAT long filename slot is not 0 " - "(but 0x%02x).\n", lfn->reserved ); - if (interactive) - printf( "1: Fix.\n2: Leave it.\n" ); - else printf( "Auto-setting to 0.\n" ); - if (!interactive || get_key("12","?") == '1') { - lfn->reserved = 0; - fs_write( dir_offset+offsetof(LFN_ENT,reserved), - sizeof(lfn->reserved), &lfn->reserved ); - } - } - if (lfn->start != CT_LE_W(0)) { - printf( "Start cluster field in VFAT long filename slot is not 0 " - "(but 0x%04x).\n", lfn->start ); - if (interactive) - printf( "1: Fix.\n2: Leave it.\n" ); - else printf( "Auto-setting to 0.\n" ); - if (!interactive || get_key("12","?") == '1') { - lfn->start = CT_LE_W(0); - fs_write( dir_offset+offsetof(LFN_ENT,start), - sizeof(lfn->start),&lfn->start ); - } - } -} - - -/* This function is always called when de->attr != VFAT_LN_ATTR is found, to - * retrieve the previously constructed LFN. */ -char *lfn_get( DIR_ENT *de ) -{ - char *lfn; - __u8 sum; - int i; - - if (de->attr == VFAT_LN_ATTR) - die("lfn_get called with LFN directory entry"); - -#if 0 - if (de->lcase) - printf( "lcase=%02x\n",de->lcase ); -#endif - - if (lfn_slot == -1) - /* no long name for this file */ - return NULL; - - if (lfn_slot != 0) { - /* The long name isn't finished yet. */ - /* Causes: 1) LFN slot overwritten by non-VFAT aware tool */ - /* Fixes: 1) delete LFN 2) move overwriting entry to somewhere else - * and let user enter missing part of LFN (hard to do :-() - * 3) renumber entries and truncate name */ - char *long_name = CNV_PARTS_SO_FAR(); - char *short_name = file_name(de->name); - printf( "Unfinished long file name \"%s\".\n" - " (Start may have been overwritten by %s)\n", - long_name, short_name ); - free( long_name ); - if (interactive) { - printf( "1: Delete LFN\n2: Leave it as it is.\n" - "3: Fix numbering (truncates long name and attaches " - "it to short name %s)\n", short_name ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( "123", "?" )) { - case '1': - clear_lfn_slots( 0, lfn_parts-1 ); - lfn_reset(); - return NULL; - case '2': - lfn_reset(); - return NULL; - case '3': - for( i = 0; i < lfn_parts; ++i ) { - __u8 id = (lfn_parts-i) | (i==0 ? LFN_ID_START : 0); - fs_write( lfn_offsets[i]+offsetof(LFN_ENT,id), - sizeof(id), &id ); - } - memmove( lfn_unicode, lfn_unicode+lfn_slot*CHARS_PER_LFN*2, - lfn_parts*CHARS_PER_LFN*2 ); - break; - } - } - } - - for (sum = 0, i = 0; i < 11; i++) - sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + de->name[i]; - if (sum != lfn_checksum) { - /* checksum doesn't match, long name doesn't apply to this alias */ - /* Causes: 1) alias renamed */ - /* Fixes: 1) Fix checksum in LFN entries */ - char *long_name = CNV_PARTS_SO_FAR(); - char *short_name = file_name(de->name); - printf( "Wrong checksum for long file name \"%s\".\n" - " (Short name %s may have changed without updating the long name)\n", - long_name, short_name ); - free( long_name ); - if (interactive) { - printf( "1: Delete LFN\n2: Leave it as it is.\n" - "3: Fix checksum (attaches to short name %s)\n", - short_name ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( "123", "?" )) { - case '1': - clear_lfn_slots( 0, lfn_parts-1 ); - lfn_reset(); - return NULL; - case '2': - lfn_reset(); - return NULL; - case '3': - for( i = 0; i < lfn_parts; ++i ) { - fs_write( lfn_offsets[i]+offsetof(LFN_ENT,alias_checksum), - sizeof(sum), &sum ); - } - break; - } - } - } - - lfn = cnv_unicode( lfn_unicode, UNTIL_0, 1 ); - lfn_reset(); - return( lfn ); -} - -void lfn_check_orphaned(void) -{ - char *long_name; - - if (lfn_slot == -1) - return; - - long_name = CNV_PARTS_SO_FAR(); - printf("Orphaned long file name part \"%s\"\n", long_name); - if (interactive) - printf( "1: Delete.\n2: Leave it.\n" ); - else printf( " Auto-deleting.\n" ); - if (!interactive || get_key("12","?") == '1') { - clear_lfn_slots(0, lfn_parts - 1); - } - lfn_reset(); -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +/* lfn.c - Functions for handling VFAT long filenames */ + +/* Written 1998 by Roman Hodek */ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "io.h" +#include "dosfsck.h" +#include "lfn.h" +#include "file.h" + +typedef struct { + __u8 id; /* sequence number for slot */ + __u8 name0_4[10]; /* first 5 characters in name */ + __u8 attr; /* attribute byte */ + __u8 reserved; /* always 0 */ + __u8 alias_checksum; /* checksum for 8.3 alias */ + __u8 name5_10[12]; /* 6 more characters in name */ + __u16 start; /* starting cluster number, 0 in long slots */ + __u8 name11_12[4]; /* last 2 characters in name */ +} LFN_ENT; + +#define LFN_ID_START 0x40 +#define LFN_ID_SLOTMASK 0x1f + +#define CHARS_PER_LFN 13 + +/* These modul-global vars represent the state of the LFN parser */ +unsigned char *lfn_unicode = NULL; +unsigned char lfn_checksum; +int lfn_slot = -1; +loff_t *lfn_offsets = NULL; +int lfn_parts = 0; + +static unsigned char fat_uni2esc[64] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', + 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', '+', '-' +}; + +/* This defines which unicode chars are directly convertable to ISO-8859-1 */ +#define UNICODE_CONVERTABLE(cl,ch) (ch == 0 && (cl < 0x80 || cl >= 0xa0)) + +/* for maxlen param */ +#define UNTIL_0 INT_MAX + +static void copy_lfn_part( char *dst, LFN_ENT *lfn ); +static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q ); + +/* Convert name part in 'lfn' from unicode to ASCII */ +static __inline char* CNV_THIS_PART(LFN_ENT *lfn) +{ \ + char __part_uni[CHARS_PER_LFN*2]; + copy_lfn_part( __part_uni, lfn ); + cnv_unicode( __part_uni, CHARS_PER_LFN, 0 ); +} + +/* Convert name parts collected so far (from previous slots) from unicode to + * ASCII */ +#define CNV_PARTS_SO_FAR() \ + (cnv_unicode( lfn_unicode+(lfn_slot*CHARS_PER_LFN*2), \ + lfn_parts*CHARS_PER_LFN, 0 )) + +/* This function converts an unicode string to a normal ASCII string, assuming + * ISO-8859-1 charset. Characters not in 8859-1 are converted to the same + * escape notation as used by the kernel, i.e. the uuencode-like ":xxx" */ +static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q ) +{ + const unsigned char *up; + unsigned char *out, *cp; + int len, val; + + for( len = 0, up = uni; (up-uni)/2 < maxlen && (up[0] || up[1]); up += 2 ){ + if (UNICODE_CONVERTABLE(up[0],up[1])) + ++len; + else + len += 4; + } + cp = out = use_q ? qalloc( &mem_queue, len+1 ) : alloc( len+1 ); + + for( up = uni; (up-uni)/2 < maxlen && (up[0] || up[1]); up += 2 ) { + if (UNICODE_CONVERTABLE(up[0],up[1])) + *cp++ = up[0]; + else { + /* here the same escape notation is used as in the Linux kernel */ + *cp++ = ':'; + val = (up[1] << 8) + up[0]; + cp[2] = fat_uni2esc[val & 0x3f]; + val >>= 6; + cp[1] = fat_uni2esc[val & 0x3f]; + val >>= 6; + cp[0] = fat_uni2esc[val & 0x3f]; + cp += 3; + } + } + *cp = 0; + + return( out ); +} + + +static void copy_lfn_part( char *dst, LFN_ENT *lfn ) +{ + memcpy( dst, lfn->name0_4, 10 ); + memcpy( dst+10, lfn->name5_10, 12 ); + memcpy( dst+22, lfn->name11_12, 4 ); +} + + +static void clear_lfn_slots( int start, int end ) +{ + int i; + LFN_ENT empty; + + /* New dir entry is zeroed except first byte, which is set to 0xe5. + * This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading + * a directory at the first zero entry... + */ + memset( &empty, 0, sizeof(empty) ); + empty.id = DELETED_FLAG; + + for( i = start; i <= end; ++i ) { + fs_write( lfn_offsets[i], sizeof(LFN_ENT), &empty ); + } +} + +void lfn_reset( void ) +{ + if (lfn_unicode) + free( lfn_unicode ); + lfn_unicode = NULL; + if (lfn_offsets) + free( lfn_offsets ); + lfn_offsets = NULL; + lfn_slot = -1; +} + + +/* This function is only called with de->attr == VFAT_LN_ATTR. It stores part + * of the long name. */ +void lfn_add_slot( DIR_ENT *de, loff_t dir_offset ) +{ + LFN_ENT *lfn = (LFN_ENT *)de; + unsigned offset; + + if (de->attr != VFAT_LN_ATTR) + die("lfn_add_slot called with non-LFN directory entry"); + + if (lfn->id & LFN_ID_START) { + if (lfn_slot != -1) { + int can_clear = 0; + /* There is already a LFN "in progess", so it is an error that a + * new start entry is here. */ + /* Causes: 1) if slot# == expected: start bit set mysteriously, 2) + * old LFN overwritten by new one */ + /* Fixes: 1) delete previous LFN 2) if slot# == expected and + * checksum ok: clear start bit */ + /* XXX: Should delay that until next LFN known (then can better + * display the name) */ + printf( "A new long file name starts within an old one.\n" ); + if ((lfn->id & LFN_ID_SLOTMASK) == lfn_slot && + lfn->alias_checksum == lfn_checksum) { + char *part1 = CNV_THIS_PART(lfn); + char *part2 = CNV_PARTS_SO_FAR(); + printf( " It could be that the LFN start bit is wrong here\n" + " if \"%s\" seems to match \"%s\".\n", part1, part2 ); + free( part1 ); + free( part2 ); + can_clear = 1; + } + if (interactive) { + printf( "1: Delete previous LFN\n2: Leave it as it is.\n" ); + if (can_clear) + printf( "3: Clear start bit and concatenate LFNs\n" ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( can_clear ? "123" : "12", "?" )) { + case '1': + clear_lfn_slots( 0, lfn_parts-1 ); + lfn_reset(); + break; + case '2': + break; + case '3': + lfn->id &= ~LFN_ID_START; + fs_write( dir_offset+offsetof(LFN_ENT,id), + sizeof(lfn->id), &lfn->id ); + break; + } + } + } + lfn_slot = lfn->id & LFN_ID_SLOTMASK; + lfn_checksum = lfn->alias_checksum; + lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 ); + lfn_offsets = alloc( lfn_slot*sizeof(loff_t) ); + lfn_parts = 0; + } + else if (lfn_slot == -1) { + /* No LFN in progress, but slot found; start bit missing */ + /* Causes: 1) start bit got lost, 2) Previous slot with start bit got + * lost */ + /* Fixes: 1) delete LFN, 2) set start bit */ + char *part = CNV_THIS_PART(lfn); + printf( "Long filename fragment \"%s\" found outside a LFN " + "sequence.\n (Maybe the start bit is missing on the " + "last fragment)\n", part ); + if (interactive) { + printf( "1: Delete fragment\n2: Leave it as it is.\n" + "3: Set start bit\n" ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( "123", "?" )) { + case '1': + if (!lfn_offsets) + lfn_offsets = alloc( sizeof(loff_t) ); + lfn_offsets[0] = dir_offset; + clear_lfn_slots( 0, 0 ); + lfn_reset(); + return; + case '2': + lfn_reset(); + return; + case '3': + lfn->id |= LFN_ID_START; + fs_write( dir_offset+offsetof(LFN_ENT,id), + sizeof(lfn->id), &lfn->id ); + lfn_slot = lfn->id & LFN_ID_SLOTMASK; + lfn_checksum = lfn->alias_checksum; + lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 ); + lfn_offsets = alloc( lfn_slot*sizeof(loff_t) ); + lfn_parts = 0; + break; + } + } + } + else if ((lfn->id & LFN_ID_SLOTMASK) != lfn_slot) { + /* wrong sequence number */ + /* Causes: 1) seq-no destroyed */ + /* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts + * are ok?, maybe only if checksum is ok?) (Attention: space + * for name was allocated before!) */ + int can_fix = 0; + printf( "Unexpected long filename sequence number " + "(%d vs. expected %d).\n", + (lfn->id & LFN_ID_SLOTMASK), lfn_slot ); + if (lfn->alias_checksum == lfn_checksum) { + char *part1 = CNV_THIS_PART(lfn); + char *part2 = CNV_PARTS_SO_FAR(); + printf( " It could be that just the number is wrong\n" + " if \"%s\" seems to match \"%s\".\n", part1, part2 ); + free( part1 ); + free( part2 ); + can_fix = 1; + } + if (interactive) { + printf( "1: Delete LFN\n2: Leave it as it is (and ignore LFN so far)\n" ); + if (can_fix) + printf( "3: Correct sequence number\n" ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( can_fix ? "123" : "12", "?" )) { + case '1': + lfn_offsets[lfn_parts++] = dir_offset; + clear_lfn_slots( 0, lfn_parts-1 ); + lfn_reset(); + return; + case '2': + lfn_reset(); + return; + case '3': + lfn->id = (lfn->id & ~LFN_ID_SLOTMASK) | lfn_slot; + fs_write( dir_offset+offsetof(LFN_ENT,id), + sizeof(lfn->id), &lfn->id ); + break; + } + } + } + + if (lfn->alias_checksum != lfn_checksum) { + /* checksum mismatch */ + /* Causes: 1) checksum field here destroyed */ + /* Fixes: 1) delete LFN, 2) fix checksum */ + printf( "Checksum in long filename part wrong " + "(%02x vs. expected %02x).\n", + lfn->alias_checksum, lfn_checksum ); + if (interactive) { + printf( "1: Delete LFN\n2: Leave it as it is.\n" + "3: Correct checksum\n" ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( "123", "?" )) { + case '1': + lfn_offsets[lfn_parts++] = dir_offset; + clear_lfn_slots( 0, lfn_parts-1 ); + lfn_reset(); + return; + case '2': + break; + case '3': + lfn->alias_checksum = lfn_checksum; + fs_write( dir_offset+offsetof(LFN_ENT,alias_checksum), + sizeof(lfn->alias_checksum), &lfn->alias_checksum ); + break; + } + } + } + + if (lfn_slot != -1) { + lfn_slot--; + offset = lfn_slot * CHARS_PER_LFN*2; + copy_lfn_part( lfn_unicode+offset, lfn ); + if (lfn->id & LFN_ID_START) + lfn_unicode[offset+26] = lfn_unicode[offset+27] = 0; + lfn_offsets[lfn_parts++] = dir_offset; + } + + if (lfn->reserved != 0) { + printf( "Reserved field in VFAT long filename slot is not 0 " + "(but 0x%02x).\n", lfn->reserved ); + if (interactive) + printf( "1: Fix.\n2: Leave it.\n" ); + else printf( "Auto-setting to 0.\n" ); + if (!interactive || get_key("12","?") == '1') { + lfn->reserved = 0; + fs_write( dir_offset+offsetof(LFN_ENT,reserved), + sizeof(lfn->reserved), &lfn->reserved ); + } + } + if (lfn->start != CT_LE_W(0)) { + printf( "Start cluster field in VFAT long filename slot is not 0 " + "(but 0x%04x).\n", lfn->start ); + if (interactive) + printf( "1: Fix.\n2: Leave it.\n" ); + else printf( "Auto-setting to 0.\n" ); + if (!interactive || get_key("12","?") == '1') { + lfn->start = CT_LE_W(0); + fs_write( dir_offset+offsetof(LFN_ENT,start), + sizeof(lfn->start),&lfn->start ); + } + } +} + + +/* This function is always called when de->attr != VFAT_LN_ATTR is found, to + * retrieve the previously constructed LFN. */ +char *lfn_get( DIR_ENT *de ) +{ + char *lfn; + __u8 sum; + int i; + + if (de->attr == VFAT_LN_ATTR) + die("lfn_get called with LFN directory entry"); + +#if 0 + if (de->lcase) + printf( "lcase=%02x\n",de->lcase ); +#endif + + if (lfn_slot == -1) + /* no long name for this file */ + return NULL; + + if (lfn_slot != 0) { + /* The long name isn't finished yet. */ + /* Causes: 1) LFN slot overwritten by non-VFAT aware tool */ + /* Fixes: 1) delete LFN 2) move overwriting entry to somewhere else + * and let user enter missing part of LFN (hard to do :-() + * 3) renumber entries and truncate name */ + char *long_name = CNV_PARTS_SO_FAR(); + char *short_name = file_name(de->name); + printf( "Unfinished long file name \"%s\".\n" + " (Start may have been overwritten by %s)\n", + long_name, short_name ); + free( long_name ); + if (interactive) { + printf( "1: Delete LFN\n2: Leave it as it is.\n" + "3: Fix numbering (truncates long name and attaches " + "it to short name %s)\n", short_name ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( "123", "?" )) { + case '1': + clear_lfn_slots( 0, lfn_parts-1 ); + lfn_reset(); + return NULL; + case '2': + lfn_reset(); + return NULL; + case '3': + for( i = 0; i < lfn_parts; ++i ) { + __u8 id = (lfn_parts-i) | (i==0 ? LFN_ID_START : 0); + fs_write( lfn_offsets[i]+offsetof(LFN_ENT,id), + sizeof(id), &id ); + } + memmove( lfn_unicode, lfn_unicode+lfn_slot*CHARS_PER_LFN*2, + lfn_parts*CHARS_PER_LFN*2 ); + break; + } + } + } + + for (sum = 0, i = 0; i < 11; i++) + sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + de->name[i]; + if (sum != lfn_checksum) { + /* checksum doesn't match, long name doesn't apply to this alias */ + /* Causes: 1) alias renamed */ + /* Fixes: 1) Fix checksum in LFN entries */ + char *long_name = CNV_PARTS_SO_FAR(); + char *short_name = file_name(de->name); + printf( "Wrong checksum for long file name \"%s\".\n" + " (Short name %s may have changed without updating the long name)\n", + long_name, short_name ); + free( long_name ); + if (interactive) { + printf( "1: Delete LFN\n2: Leave it as it is.\n" + "3: Fix checksum (attaches to short name %s)\n", + short_name ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( "123", "?" )) { + case '1': + clear_lfn_slots( 0, lfn_parts-1 ); + lfn_reset(); + return NULL; + case '2': + lfn_reset(); + return NULL; + case '3': + for( i = 0; i < lfn_parts; ++i ) { + fs_write( lfn_offsets[i]+offsetof(LFN_ENT,alias_checksum), + sizeof(sum), &sum ); + } + break; + } + } + } + + lfn = cnv_unicode( lfn_unicode, UNTIL_0, 1 ); + lfn_reset(); + return( lfn ); +} + +void lfn_check_orphaned(void) +{ + char *long_name; + + if (lfn_slot == -1) + return; + + long_name = CNV_PARTS_SO_FAR(); + printf("Orphaned long file name part \"%s\"\n", long_name); + if (interactive) + printf( "1: Delete.\n2: Leave it.\n" ); + else printf( " Auto-deleting.\n" ); + if (!interactive || get_key("12","?") == '1') { + clear_lfn_slots(0, lfn_parts - 1); + } + lfn_reset(); +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/lfn.h b/rosapps/sysutils/dosfsck/lfn.h index d062e4a39c8..21726ef858b 100644 --- a/rosapps/sysutils/dosfsck/lfn.h +++ b/rosapps/sysutils/dosfsck/lfn.h @@ -1,20 +1,20 @@ -/* lfn.h - Functions for handling VFAT long filenames */ - -/* Written 1998 by Roman Hodek */ - - -#ifndef _LFN_H -#define _LFN_H - -void lfn_reset( void ); -/* Reset the state of the LFN parser. */ - -void lfn_add_slot( DIR_ENT *de, loff_t dir_offset ); -/* Process a dir slot that is a VFAT LFN entry. */ - -char *lfn_get( DIR_ENT *de ); -/* Retrieve the long name for the proper dir entry. */ - -void lfn_check_orphaned(void); - -#endif +/* lfn.h - Functions for handling VFAT long filenames */ + +/* Written 1998 by Roman Hodek */ + + +#ifndef _LFN_H +#define _LFN_H + +void lfn_reset( void ); +/* Reset the state of the LFN parser. */ + +void lfn_add_slot( DIR_ENT *de, loff_t dir_offset ); +/* Process a dir slot that is a VFAT LFN entry. */ + +char *lfn_get( DIR_ENT *de ); +/* Retrieve the long name for the proper dir entry. */ + +void lfn_check_orphaned(void); + +#endif diff --git a/rosapps/sysutils/dosfsck/msdos_fs.h b/rosapps/sysutils/dosfsck/msdos_fs.h index 5647fe833cd..b955808df9a 100644 --- a/rosapps/sysutils/dosfsck/msdos_fs.h +++ b/rosapps/sysutils/dosfsck/msdos_fs.h @@ -1,182 +1,182 @@ -#ifndef _LINUX_MSDOS_FS_H -#define _LINUX_MSDOS_FS_H - -/* - * The MS-DOS filesystem constants/structures - */ -#include "byteorder.h" - -#define SECTOR_SIZE 512 /* sector size (bytes) */ -#define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */ -#define MSDOS_DPB (MSDOS_DPS) /* dir entries per block */ -#define MSDOS_DPB_BITS 4 /* log2(MSDOS_DPB) */ -#define MSDOS_DPS (SECTOR_SIZE / sizeof(struct msdos_dir_entry)) -#define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */ -#if 0 -#define CF_LE_W(v) le16_to_cpu(v) -#define CF_LE_L(v) le32_to_cpu(v) -#define CT_LE_W(v) cpu_to_le16(v) -#define CT_LE_L(v) cpu_to_le32(v) -#endif - -#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ - -#define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */ -#define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */ - -/* directory limit */ -#define FAT_MAX_DIR_ENTRIES (65536) -#define FAT_MAX_DIR_SIZE (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS) - -#define ATTR_NONE 0 /* no attribute bits */ -#define ATTR_RO 1 /* read-only */ -#define ATTR_HIDDEN 2 /* hidden */ -#define ATTR_SYS 4 /* system */ -#define ATTR_VOLUME 8 /* volume label */ -#define ATTR_DIR 16 /* directory */ -#define ATTR_ARCH 32 /* archived */ - -/* attribute bits that are copied "as is" */ -#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN) -/* bits that are used by the Windows 95/Windows NT extended FAT */ -#define ATTR_EXT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) - -#define CASE_LOWER_BASE 8 /* base is lower case */ -#define CASE_LOWER_EXT 16 /* extension is lower case */ - -#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ -#define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG) - -/* valid file mode bits */ -#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO) -/* Convert attribute bits and a mask to the UNIX mode. */ -#define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO)) - -#define MSDOS_NAME 11 /* maximum name length */ -#define MSDOS_LONGNAME 256 /* maximum name length */ -#define MSDOS_SLOTS 21 /* max # of slots for short and long names */ -#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */ -#define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */ - -/* media of boot sector */ -#define FAT_VALID_MEDIA(x) ((0xF8 <= (x) && (x) <= 0xFF) || (x) == 0xF0) -#define FAT_FIRST_ENT(s, x) ((MSDOS_SB(s)->fat_bits == 32 ? 0x0FFFFF00 : \ - MSDOS_SB(s)->fat_bits == 16 ? 0xFF00 : 0xF00) | (x)) - -/* start of data cluster's entry (number of reserved clusters) */ -#define FAT_START_ENT 2 - -/* maximum number of clusters */ -#define MAX_FAT12 0xFF4 -#define MAX_FAT16 0xFFF4 -#define MAX_FAT32 0x0FFFFFF6 -#define MAX_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? MAX_FAT32 : \ - MSDOS_SB(s)->fat_bits == 16 ? MAX_FAT16 : MAX_FAT12) - -/* bad cluster mark */ -#define BAD_FAT12 0xFF7 -#define BAD_FAT16 0xFFF7 -#define BAD_FAT32 0x0FFFFFF7 - -/* standard EOF */ -#define EOF_FAT12 0xFFF -#define EOF_FAT16 0xFFFF -#define EOF_FAT32 0x0FFFFFFF - -#define FAT_ENT_FREE (0) -#define FAT_ENT_BAD (BAD_FAT32) -#define FAT_ENT_EOF (EOF_FAT32) - -#define FAT_FSINFO_SIG1 0x41615252 -#define FAT_FSINFO_SIG2 0x61417272 -#define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \ - && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2) - -/* - * ioctl commands - */ -#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) -#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) -/* has used 0x72 ('r') in collision, so skip a few */ -#define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) -#define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32) - -/* - * vfat shortname flags - */ -#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ -#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ -#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ -#define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ -#define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ - -struct fat_boot_sector { - __u8 ignored[3]; /* Boot strap short or near jump */ - __u8 system_id[8]; /* Name - can be used to special case - partition manager volumes */ - __u8 sector_size[2]; /* bytes per logical sector */ - __u8 sec_per_clus; /* sectors/cluster */ - __le16 reserved; /* reserved sectors */ - __u8 fats; /* number of FATs */ - __u8 dir_entries[2]; /* root directory entries */ - __u8 sectors[2]; /* number of sectors */ - __u8 media; /* media code */ - __le16 fat_length; /* sectors/FAT */ - __le16 secs_track; /* sectors per track */ - __le16 heads; /* number of heads */ - __le32 hidden; /* hidden sectors (unused) */ - __le32 total_sect; /* number of sectors (if sectors == 0) */ - - /* The following fields are only used by FAT32 */ - __le32 fat32_length; /* sectors/FAT */ - __le16 flags; /* bit 8: fat mirroring, low 4: active fat */ - __u8 version[2]; /* major, minor filesystem version */ - __le32 root_cluster; /* first cluster in root directory */ - __le16 info_sector; /* filesystem info sector */ - __le16 backup_boot; /* backup boot sector */ - __le16 reserved2[6]; /* Unused */ -}; - -struct fat_boot_fsinfo { - __le32 signature1; /* 0x41615252L */ - __le32 reserved1[120]; /* Nothing as far as I can tell */ - __le32 signature2; /* 0x61417272L */ - __le32 free_clusters; /* Free cluster count. -1 if unknown */ - __le32 next_cluster; /* Most recently allocated cluster */ - __le32 reserved2[4]; -}; - -struct msdos_dir_entry { - __u8 name[8],ext[3]; /* name and extension */ - __u8 attr; /* attribute bits */ - __u8 lcase; /* Case for base and extension */ - __u8 ctime_cs; /* Creation time, centiseconds (0-199) */ - __le16 ctime; /* Creation time */ - __le16 cdate; /* Creation date */ - __le16 adate; /* Last access date */ - __le16 starthi; /* High 16 bits of cluster in FAT32 */ - __le16 time,date,start;/* time, date and first cluster */ - __le32 size; /* file size (in bytes) */ -}; - -/* Up to 13 characters of the name */ -struct msdos_dir_slot { - __u8 id; /* sequence number for slot */ - __u8 name0_4[10]; /* first 5 characters in name */ - __u8 attr; /* attribute byte */ - __u8 reserved; /* always 0 */ - __u8 alias_checksum; /* checksum for 8.3 alias */ - __u8 name5_10[12]; /* 6 more characters in name */ - __le16 start; /* starting cluster number, 0 in long slots */ - __u8 name11_12[4]; /* last 2 characters in name */ -}; - -struct fat_slot_info { - loff_t i_pos; /* on-disk position of directory entry */ - loff_t slot_off; /* offset for slot or de start */ - int nr_slots; /* number of slots + 1(de) in filename */ - struct msdos_dir_entry *de; - struct buffer_head *bh; -}; - -#endif +#ifndef _LINUX_MSDOS_FS_H +#define _LINUX_MSDOS_FS_H + +/* + * The MS-DOS filesystem constants/structures + */ +#include "byteorder.h" + +#define SECTOR_SIZE 512 /* sector size (bytes) */ +#define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */ +#define MSDOS_DPB (MSDOS_DPS) /* dir entries per block */ +#define MSDOS_DPB_BITS 4 /* log2(MSDOS_DPB) */ +#define MSDOS_DPS (SECTOR_SIZE / sizeof(struct msdos_dir_entry)) +#define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */ +#if 0 +#define CF_LE_W(v) le16_to_cpu(v) +#define CF_LE_L(v) le32_to_cpu(v) +#define CT_LE_W(v) cpu_to_le16(v) +#define CT_LE_L(v) cpu_to_le32(v) +#endif + +#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ + +#define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */ +#define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */ + +/* directory limit */ +#define FAT_MAX_DIR_ENTRIES (65536) +#define FAT_MAX_DIR_SIZE (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS) + +#define ATTR_NONE 0 /* no attribute bits */ +#define ATTR_RO 1 /* read-only */ +#define ATTR_HIDDEN 2 /* hidden */ +#define ATTR_SYS 4 /* system */ +#define ATTR_VOLUME 8 /* volume label */ +#define ATTR_DIR 16 /* directory */ +#define ATTR_ARCH 32 /* archived */ + +/* attribute bits that are copied "as is" */ +#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN) +/* bits that are used by the Windows 95/Windows NT extended FAT */ +#define ATTR_EXT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) + +#define CASE_LOWER_BASE 8 /* base is lower case */ +#define CASE_LOWER_EXT 16 /* extension is lower case */ + +#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ +#define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG) + +/* valid file mode bits */ +#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO) +/* Convert attribute bits and a mask to the UNIX mode. */ +#define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO)) + +#define MSDOS_NAME 11 /* maximum name length */ +#define MSDOS_LONGNAME 256 /* maximum name length */ +#define MSDOS_SLOTS 21 /* max # of slots for short and long names */ +#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */ +#define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */ + +/* media of boot sector */ +#define FAT_VALID_MEDIA(x) ((0xF8 <= (x) && (x) <= 0xFF) || (x) == 0xF0) +#define FAT_FIRST_ENT(s, x) ((MSDOS_SB(s)->fat_bits == 32 ? 0x0FFFFF00 : \ + MSDOS_SB(s)->fat_bits == 16 ? 0xFF00 : 0xF00) | (x)) + +/* start of data cluster's entry (number of reserved clusters) */ +#define FAT_START_ENT 2 + +/* maximum number of clusters */ +#define MAX_FAT12 0xFF4 +#define MAX_FAT16 0xFFF4 +#define MAX_FAT32 0x0FFFFFF6 +#define MAX_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? MAX_FAT32 : \ + MSDOS_SB(s)->fat_bits == 16 ? MAX_FAT16 : MAX_FAT12) + +/* bad cluster mark */ +#define BAD_FAT12 0xFF7 +#define BAD_FAT16 0xFFF7 +#define BAD_FAT32 0x0FFFFFF7 + +/* standard EOF */ +#define EOF_FAT12 0xFFF +#define EOF_FAT16 0xFFFF +#define EOF_FAT32 0x0FFFFFFF + +#define FAT_ENT_FREE (0) +#define FAT_ENT_BAD (BAD_FAT32) +#define FAT_ENT_EOF (EOF_FAT32) + +#define FAT_FSINFO_SIG1 0x41615252 +#define FAT_FSINFO_SIG2 0x61417272 +#define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \ + && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2) + +/* + * ioctl commands + */ +#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) +#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) +/* has used 0x72 ('r') in collision, so skip a few */ +#define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) +#define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32) + +/* + * vfat shortname flags + */ +#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ +#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ +#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ +#define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ +#define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ + +struct fat_boot_sector { + __u8 ignored[3]; /* Boot strap short or near jump */ + __u8 system_id[8]; /* Name - can be used to special case + partition manager volumes */ + __u8 sector_size[2]; /* bytes per logical sector */ + __u8 sec_per_clus; /* sectors/cluster */ + __le16 reserved; /* reserved sectors */ + __u8 fats; /* number of FATs */ + __u8 dir_entries[2]; /* root directory entries */ + __u8 sectors[2]; /* number of sectors */ + __u8 media; /* media code */ + __le16 fat_length; /* sectors/FAT */ + __le16 secs_track; /* sectors per track */ + __le16 heads; /* number of heads */ + __le32 hidden; /* hidden sectors (unused) */ + __le32 total_sect; /* number of sectors (if sectors == 0) */ + + /* The following fields are only used by FAT32 */ + __le32 fat32_length; /* sectors/FAT */ + __le16 flags; /* bit 8: fat mirroring, low 4: active fat */ + __u8 version[2]; /* major, minor filesystem version */ + __le32 root_cluster; /* first cluster in root directory */ + __le16 info_sector; /* filesystem info sector */ + __le16 backup_boot; /* backup boot sector */ + __le16 reserved2[6]; /* Unused */ +}; + +struct fat_boot_fsinfo { + __le32 signature1; /* 0x41615252L */ + __le32 reserved1[120]; /* Nothing as far as I can tell */ + __le32 signature2; /* 0x61417272L */ + __le32 free_clusters; /* Free cluster count. -1 if unknown */ + __le32 next_cluster; /* Most recently allocated cluster */ + __le32 reserved2[4]; +}; + +struct msdos_dir_entry { + __u8 name[8],ext[3]; /* name and extension */ + __u8 attr; /* attribute bits */ + __u8 lcase; /* Case for base and extension */ + __u8 ctime_cs; /* Creation time, centiseconds (0-199) */ + __le16 ctime; /* Creation time */ + __le16 cdate; /* Creation date */ + __le16 adate; /* Last access date */ + __le16 starthi; /* High 16 bits of cluster in FAT32 */ + __le16 time,date,start;/* time, date and first cluster */ + __le32 size; /* file size (in bytes) */ +}; + +/* Up to 13 characters of the name */ +struct msdos_dir_slot { + __u8 id; /* sequence number for slot */ + __u8 name0_4[10]; /* first 5 characters in name */ + __u8 attr; /* attribute byte */ + __u8 reserved; /* always 0 */ + __u8 alias_checksum; /* checksum for 8.3 alias */ + __u8 name5_10[12]; /* 6 more characters in name */ + __le16 start; /* starting cluster number, 0 in long slots */ + __u8 name11_12[4]; /* last 2 characters in name */ +}; + +struct fat_slot_info { + loff_t i_pos; /* on-disk position of directory entry */ + loff_t slot_off; /* offset for slot or de start */ + int nr_slots; /* number of slots + 1(de) in filename */ + struct msdos_dir_entry *de; + struct buffer_head *bh; +}; + +#endif diff --git a/rosapps/sysutils/dosfsck/swab.h b/rosapps/sysutils/dosfsck/swab.h index 647648c7aa6..31bd29157f0 100644 --- a/rosapps/sysutils/dosfsck/swab.h +++ b/rosapps/sysutils/dosfsck/swab.h @@ -1,192 +1,192 @@ -#ifndef _LINUX_BYTEORDER_SWAB_H -#define _LINUX_BYTEORDER_SWAB_H - -/* - * linux/byteorder/swab.h - * Byte-swapping, independently from CPU endianness - * swabXX[ps]?(foo) - * - * Francois-Rene Rideau 19971205 - * separated swab functions from cpu_to_XX, - * to clean up support for bizarre-endian architectures. - * - * See asm-i386/byteorder.h and suches for examples of how to provide - * architecture-dependent optimized versions - * - */ - -#include "compiler.h" - -/* casts are necessary for constants, because we never know how for sure - * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. - */ -#define ___swab16(x) \ -({ \ - __u16 __x = (x); \ - ((__u16)( \ - (((__u16)(__x) & (__u16)0x00ffU) << 8) | \ - (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \ -}) - -#define ___swab32(x) \ -({ \ - __u32 __x = (x); \ - ((__u32)( \ - (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \ - (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \ - (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \ - (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \ -}) - -#define ___swab64(x) \ -({ \ - __u64 __x = (x); \ - ((__u64)( \ - (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \ - (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \ - (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \ - (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \ - (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \ - (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ - (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \ - (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \ -}) - -#define ___constant_swab16(x) \ - ((__u16)( \ - (((__u16)(x) & (__u16)0x00ffU) << 8) | \ - (((__u16)(x) & (__u16)0xff00U) >> 8) )) -#define ___constant_swab32(x) \ - ((__u32)( \ - (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ - (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ - (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ - (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) -#define ___constant_swab64(x) \ - ((__u64)( \ - (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ - (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ - (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ - (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ - (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ - (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ - (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ - (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) )) - -/* - * provide defaults when no architecture-specific optimization is detected - */ -#ifndef __arch__swab16 -# define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); }) -#endif -#ifndef __arch__swab32 -# define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); }) -#endif -#ifndef __arch__swab64 -# define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); }) -#endif - -#ifndef __arch__swab16p -# define __arch__swab16p(x) __arch__swab16(*(x)) -#endif -#ifndef __arch__swab32p -# define __arch__swab32p(x) __arch__swab32(*(x)) -#endif -#ifndef __arch__swab64p -# define __arch__swab64p(x) __arch__swab64(*(x)) -#endif - -#ifndef __arch__swab16s -# define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0) -#endif -#ifndef __arch__swab32s -# define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0) -#endif -#ifndef __arch__swab64s -# define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0) -#endif - - -/* - * Allow constant folding - */ -#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__) -# define __swab16(x) \ -(__builtin_constant_p((__u16)(x)) ? \ - ___swab16((x)) : \ - __fswab16((x))) -# define __swab32(x) \ -(__builtin_constant_p((__u32)(x)) ? \ - ___swab32((x)) : \ - __fswab32((x))) -# define __swab64(x) \ -(__builtin_constant_p((__u64)(x)) ? \ - ___swab64((x)) : \ - __fswab64((x))) -#else -# define __swab16(x) __fswab16(x) -# define __swab32(x) __fswab32(x) -# define __swab64(x) __fswab64(x) -#endif /* OPTIMIZE */ - - -static __inline__ __attribute_const__ __u16 __fswab16(__u16 x) -{ - return __arch__swab16(x); -} -static __inline__ __u16 __swab16p(const __u16 *x) -{ - return __arch__swab16p(x); -} -static __inline__ void __swab16s(__u16 *addr) -{ - __arch__swab16s(addr); -} - -static __inline__ __attribute_const__ __u32 __fswab32(__u32 x) -{ - return __arch__swab32(x); -} -static __inline__ __u32 __swab32p(const __u32 *x) -{ - return __arch__swab32p(x); -} -static __inline__ void __swab32s(__u32 *addr) -{ - __arch__swab32s(addr); -} - -#ifdef __BYTEORDER_HAS_U64__ -static __inline__ __attribute_const__ __u64 __fswab64(__u64 x) -{ -# ifdef __SWAB_64_THRU_32__ - __u32 h = x >> 32; - __u32 l = x & ((1ULL<<32)-1); - return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h))); -# else - return __arch__swab64(x); -# endif -} -static __inline__ __u64 __swab64p(const __u64 *x) -{ - return __arch__swab64p(x); -} -static __inline__ void __swab64s(__u64 *addr) -{ - __arch__swab64s(addr); -} -#endif /* __BYTEORDER_HAS_U64__ */ - -#if defined(__KERNEL__) -#define swab16 __swab16 -#define swab32 __swab32 -#define swab64 __swab64 -#define swab16p __swab16p -#define swab32p __swab32p -#define swab64p __swab64p -#define swab16s __swab16s -#define swab32s __swab32s -#define swab64s __swab64s -#endif - -#endif /* _LINUX_BYTEORDER_SWAB_H */ +#ifndef _LINUX_BYTEORDER_SWAB_H +#define _LINUX_BYTEORDER_SWAB_H + +/* + * linux/byteorder/swab.h + * Byte-swapping, independently from CPU endianness + * swabXX[ps]?(foo) + * + * Francois-Rene Rideau 19971205 + * separated swab functions from cpu_to_XX, + * to clean up support for bizarre-endian architectures. + * + * See asm-i386/byteorder.h and suches for examples of how to provide + * architecture-dependent optimized versions + * + */ + +#include "compiler.h" + +/* casts are necessary for constants, because we never know how for sure + * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. + */ +#define ___swab16(x) \ +({ \ + __u16 __x = (x); \ + ((__u16)( \ + (((__u16)(__x) & (__u16)0x00ffU) << 8) | \ + (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \ +}) + +#define ___swab32(x) \ +({ \ + __u32 __x = (x); \ + ((__u32)( \ + (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \ +}) + +#define ___swab64(x) \ +({ \ + __u64 __x = (x); \ + ((__u64)( \ + (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \ + (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \ + (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \ + (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \ + (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \ + (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ + (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \ + (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \ +}) + +#define ___constant_swab16(x) \ + ((__u16)( \ + (((__u16)(x) & (__u16)0x00ffU) << 8) | \ + (((__u16)(x) & (__u16)0xff00U) >> 8) )) +#define ___constant_swab32(x) \ + ((__u32)( \ + (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) +#define ___constant_swab64(x) \ + ((__u64)( \ + (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ + (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ + (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ + (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ + (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ + (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ + (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ + (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) )) + +/* + * provide defaults when no architecture-specific optimization is detected + */ +#ifndef __arch__swab16 +# define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); }) +#endif +#ifndef __arch__swab32 +# define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); }) +#endif +#ifndef __arch__swab64 +# define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); }) +#endif + +#ifndef __arch__swab16p +# define __arch__swab16p(x) __arch__swab16(*(x)) +#endif +#ifndef __arch__swab32p +# define __arch__swab32p(x) __arch__swab32(*(x)) +#endif +#ifndef __arch__swab64p +# define __arch__swab64p(x) __arch__swab64(*(x)) +#endif + +#ifndef __arch__swab16s +# define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0) +#endif +#ifndef __arch__swab32s +# define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0) +#endif +#ifndef __arch__swab64s +# define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0) +#endif + + +/* + * Allow constant folding + */ +#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__) +# define __swab16(x) \ +(__builtin_constant_p((__u16)(x)) ? \ + ___swab16((x)) : \ + __fswab16((x))) +# define __swab32(x) \ +(__builtin_constant_p((__u32)(x)) ? \ + ___swab32((x)) : \ + __fswab32((x))) +# define __swab64(x) \ +(__builtin_constant_p((__u64)(x)) ? \ + ___swab64((x)) : \ + __fswab64((x))) +#else +# define __swab16(x) __fswab16(x) +# define __swab32(x) __fswab32(x) +# define __swab64(x) __fswab64(x) +#endif /* OPTIMIZE */ + + +static __inline__ __attribute_const__ __u16 __fswab16(__u16 x) +{ + return __arch__swab16(x); +} +static __inline__ __u16 __swab16p(const __u16 *x) +{ + return __arch__swab16p(x); +} +static __inline__ void __swab16s(__u16 *addr) +{ + __arch__swab16s(addr); +} + +static __inline__ __attribute_const__ __u32 __fswab32(__u32 x) +{ + return __arch__swab32(x); +} +static __inline__ __u32 __swab32p(const __u32 *x) +{ + return __arch__swab32p(x); +} +static __inline__ void __swab32s(__u32 *addr) +{ + __arch__swab32s(addr); +} + +#ifdef __BYTEORDER_HAS_U64__ +static __inline__ __attribute_const__ __u64 __fswab64(__u64 x) +{ +# ifdef __SWAB_64_THRU_32__ + __u32 h = x >> 32; + __u32 l = x & ((1ULL<<32)-1); + return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h))); +# else + return __arch__swab64(x); +# endif +} +static __inline__ __u64 __swab64p(const __u64 *x) +{ + return __arch__swab64p(x); +} +static __inline__ void __swab64s(__u64 *addr) +{ + __arch__swab64s(addr); +} +#endif /* __BYTEORDER_HAS_U64__ */ + +#if defined(__KERNEL__) +#define swab16 __swab16 +#define swab32 __swab32 +#define swab64 __swab64 +#define swab16p __swab16p +#define swab32p __swab32p +#define swab64p __swab64p +#define swab16s __swab16s +#define swab32s __swab32s +#define swab64s __swab64s +#endif + +#endif /* _LINUX_BYTEORDER_SWAB_H */ diff --git a/rosapps/sysutils/dosfsck/version.h b/rosapps/sysutils/dosfsck/version.h index e0878fb50bc..4ef269483fe 100644 --- a/rosapps/sysutils/dosfsck/version.h +++ b/rosapps/sysutils/dosfsck/version.h @@ -1,8 +1,8 @@ -#ifndef _version_h -#define _version_h - -#define VERSION "2.8" -#define VERSION_DATE "28 Feb 2001" - -#endif /* _version_h */ - +#ifndef _version_h +#define _version_h + +#define VERSION "2.8" +#define VERSION_DATE "28 Feb 2001" + +#endif /* _version_h */ + diff --git a/rosapps/sysutils/dosfsck/vfat.h b/rosapps/sysutils/dosfsck/vfat.h index 6f2e7cea6a4..72953d8216b 100755 --- a/rosapps/sysutils/dosfsck/vfat.h +++ b/rosapps/sysutils/dosfsck/vfat.h @@ -1,744 +1,744 @@ -/* $Id: vfat.h 16656 2005-07-20 02:52:52Z ion $ */ - -#include -#include -#include -#include -#include -#include -#include - -#define USE_ROS_CC_AND_FS - -#include -struct _BootSector -{ - unsigned char magic0, res0, magic1; - unsigned char OEMName[8]; - unsigned short BytesPerSector; - unsigned char SectorsPerCluster; - unsigned short ReservedSectors; - unsigned char FATCount; - unsigned short RootEntries, Sectors; - unsigned char Media; - unsigned short FATSectors, SectorsPerTrack, Heads; - unsigned long HiddenSectors, SectorsHuge; - unsigned char Drive, Res1, Sig; - unsigned long VolumeID; - unsigned char VolumeLabel[11], SysType[8]; - unsigned char Res2[448]; - unsigned short Signatur1; -}; - -struct _BootSector32 -{ - unsigned char magic0, res0, magic1; // 0 - unsigned char OEMName[8]; // 3 - unsigned short BytesPerSector; // 11 - unsigned char SectorsPerCluster; // 13 - unsigned short ReservedSectors; // 14 - unsigned char FATCount; // 16 - unsigned short RootEntries, Sectors; // 17 - unsigned char Media; // 21 - unsigned short FATSectors, SectorsPerTrack, Heads; // 22 - unsigned long HiddenSectors, SectorsHuge; // 28 - unsigned long FATSectors32; // 36 - unsigned short ExtFlag; // 40 - unsigned short FSVersion; // 42 - unsigned long RootCluster; // 44 - unsigned short FSInfoSector; // 48 - unsigned short BootBackup; // 50 - unsigned char Res3[12]; // 52 - unsigned char Drive; // 64 - unsigned char Res4; // 65 - unsigned char ExtBootSignature; // 66 - unsigned long VolumeID; // 67 - unsigned char VolumeLabel[11], SysType[8]; // 71 - unsigned char Res2[420]; // 90 - unsigned short Signature1; // 510 -}; - -struct _BootSectorFatX -{ - unsigned char SysType[4]; // 0 - unsigned long VolumeID; // 4 - unsigned long SectorsPerCluster; // 8 - unsigned short FATCount; // 12 - unsigned long Unknown; // 14 - unsigned char Unused[4078]; // 18 -}; - -struct _FsInfoSector -{ - unsigned long ExtBootSignature2; // 0 - unsigned char Res6[480]; // 4 - unsigned long FSINFOSignature; // 484 - unsigned long FreeCluster; // 488 - unsigned long NextCluster; // 492 - unsigned char Res7[12]; // 496 - unsigned long Signatur2; // 508 -}; - -typedef struct _BootSector BootSector; - -struct _FATDirEntry -{ - union - { - struct { unsigned char Filename[8], Ext[3]; }; - unsigned char ShortName[11]; - }; - unsigned char Attrib; - unsigned char lCase; - unsigned char CreationTimeMs; - unsigned short CreationTime,CreationDate,AccessDate; - unsigned short FirstClusterHigh; // higher - unsigned short UpdateTime; //time create/update - unsigned short UpdateDate; //date create/update - unsigned short FirstCluster; - unsigned long FileSize; -}; - -typedef struct _FATDirEntry FAT_DIR_ENTRY, *PFAT_DIR_ENTRY; - -struct _FATXDirEntry -{ - unsigned char FilenameLength; // 0 - unsigned char Attrib; // 1 - unsigned char Filename[42]; // 2 - unsigned long FirstCluster; // 44 - unsigned long FileSize; // 48 - unsigned short UpdateTime; // 52 - unsigned short UpdateDate; // 54 - unsigned short CreationTime; // 56 - unsigned short CreationDate; // 58 - unsigned short AccessTime; // 60 - unsigned short AccessDate; // 62 -}; - -struct _slot -{ - unsigned char id; // sequence number for slot - WCHAR name0_4[5]; // first 5 characters in name - unsigned char attr; // attribute byte - unsigned char reserved; // always 0 - unsigned char alias_checksum; // checksum for 8.3 alias - WCHAR name5_10[6]; // 6 more characters in name - unsigned char start[2]; // starting cluster number - WCHAR name11_12[2]; // last 2 characters in name -}; - -typedef struct _slot slot; - -#include - -#define VFAT_CASE_LOWER_BASE 8 // base is lower case -#define VFAT_CASE_LOWER_EXT 16 // extension is lower case - -#define LONGNAME_MAX_LENGTH 256 // max length for a long filename - -#define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat))) -#define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat))) -#define ENTRY_END(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat))) - -#define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5) -#define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0) -#define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f) -#define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08) - -#define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5) -#define FATX_ENTRY_END(DirEntry) ((DirEntry)->FilenameLength == 0xff) -#define FATX_ENTRY_LONG(DirEntry) (FALSE) -#define FATX_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08) - -#define FAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FAT_DIR_ENTRY)) -#define FATX_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATX_DIR_ENTRY)) - -typedef struct _FATXDirEntry FATX_DIR_ENTRY, *PFATX_DIR_ENTRY; - -union _DIR_ENTRY -{ - FAT_DIR_ENTRY Fat; - FATX_DIR_ENTRY FatX; -}; - -typedef union _DIR_ENTRY DIR_ENTRY, *PDIR_ENTRY; - -#define BLOCKSIZE 512 - -#define FAT16 (1) -#define FAT12 (2) -#define FAT32 (3) -#define FATX16 (4) -#define FATX32 (5) - -#define VCB_VOLUME_LOCKED 0x0001 -#define VCB_DISMOUNT_PENDING 0x0002 -#define VCB_IS_FATX 0x0004 -#define VCB_IS_DIRTY 0x4000 /* Volume is dirty */ -#define VCB_CLEAR_DIRTY 0x8000 /* Clean dirty flag at shutdown */ - -typedef struct -{ - ULONG VolumeID; - ULONG FATStart; - ULONG FATCount; - ULONG FATSectors; - ULONG rootDirectorySectors; - ULONG rootStart; - ULONG dataStart; - ULONG RootCluster; - ULONG SectorsPerCluster; - ULONG BytesPerSector; - ULONG BytesPerCluster; - ULONG NumberOfClusters; - ULONG FatType; - ULONG Sectors; - BOOLEAN FixedMedia; -} FATINFO, *PFATINFO; - -struct _VFATFCB; -struct _VFAT_DIRENTRY_CONTEXT; - -typedef struct _HASHENTRY -{ - ULONG Hash; - struct _VFATFCB* self; - struct _HASHENTRY* next; -} -HASHENTRY; - -#define FCB_HASH_TABLE_SIZE 65536 - -typedef struct DEVICE_EXTENSION *PDEVICE_EXTENSION; - -typedef NTSTATUS (*PGET_NEXT_CLUSTER)(PDEVICE_EXTENSION,ULONG,PULONG); -typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER)(PDEVICE_EXTENSION,PULONG); -typedef NTSTATUS (*PWRITE_CLUSTER)(PDEVICE_EXTENSION,ULONG,ULONG,PULONG); - -typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY)(PVOID*,PVOID*,struct _VFATFCB*,struct _VFAT_DIRENTRY_CONTEXT*,BOOLEAN); - -typedef struct DEVICE_EXTENSION -{ - ERESOURCE DirResource; - ERESOURCE FatResource; - - KSPIN_LOCK FcbListLock; - LIST_ENTRY FcbListHead; - ULONG HashTableSize; - struct _HASHENTRY** FcbHashTable; - - PDEVICE_OBJECT StorageDevice; - PFILE_OBJECT FATFileObject; - FATINFO FatInfo; - ULONG LastAvailableCluster; - ULONG AvailableClusters; - BOOLEAN AvailableClustersValid; - ULONG Flags; - struct _VFATFCB * VolumeFcb; - - /* Pointers to functions for manipulating FAT. */ - PGET_NEXT_CLUSTER GetNextCluster; - PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster; - PWRITE_CLUSTER WriteCluster; - ULONG CleanShutBitMask; - - /* Pointers to functions for manipulating directory entries. */ - PGET_NEXT_DIR_ENTRY GetNextDirEntry; - - ULONG BaseDateYear; - - LIST_ENTRY VolumeListEntry; -} DEVICE_EXTENSION, VCB, *PVCB; - -typedef struct -{ - PDRIVER_OBJECT DriverObject; - PDEVICE_OBJECT DeviceObject; - ULONG Flags; - ERESOURCE VolumeListLock; - LIST_ENTRY VolumeListHead; - NPAGED_LOOKASIDE_LIST FcbLookasideList; - NPAGED_LOOKASIDE_LIST CcbLookasideList; - NPAGED_LOOKASIDE_LIST IrpContextLookasideList; - FAST_IO_DISPATCH FastIoDispatch; - CACHE_MANAGER_CALLBACKS CacheMgrCallbacks; -} VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA; - -extern PVFAT_GLOBAL_DATA VfatGlobalData; - -#define FCB_CACHE_INITIALIZED 0x0001 -#define FCB_DELETE_PENDING 0x0002 -#define FCB_IS_FAT 0x0004 -#define FCB_IS_PAGE_FILE 0x0008 -#define FCB_IS_VOLUME 0x0010 -#define FCB_IS_DIRTY 0x0020 -#define FCB_IS_FATX_ENTRY 0x0040 - -typedef struct _VFATFCB -{ - /* FCB header required by ROS/NT */ - FSRTL_COMMON_FCB_HEADER RFCB; - SECTION_OBJECT_POINTERS SectionObjectPointers; - ERESOURCE MainResource; - ERESOURCE PagingIoResource; - /* end FCB header required by ROS/NT */ - - /* directory entry for this file or directory */ - DIR_ENTRY entry; - - /* Pointer to attributes in entry */ - PUCHAR Attributes; - - /* long file name, points into PathNameBuffer */ - UNICODE_STRING LongNameU; - - /* short file name */ - UNICODE_STRING ShortNameU; - - /* directory name, points into PathNameBuffer */ - UNICODE_STRING DirNameU; - - /* path + long file name 260 max*/ - UNICODE_STRING PathNameU; - - /* buffer for PathNameU */ - PWCHAR PathNameBuffer; - - /* buffer for ShortNameU */ - WCHAR ShortNameBuffer[13]; - - /* */ - LONG RefCount; - - /* List of FCB's for this volume */ - LIST_ENTRY FcbListEntry; - - /* pointer to the parent fcb */ - struct _VFATFCB* parentFcb; - - /* Flags for the fcb */ - ULONG Flags; - - /* pointer to the file object which has initialized the fcb */ - PFILE_OBJECT FileObject; - - /* Directory index for the short name entry */ - ULONG dirIndex; - - /* Directory index where the long name starts */ - ULONG startIndex; - - /* Share access for the file object */ - SHARE_ACCESS FCBShareAccess; - - /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */ - ULONG OpenHandleCount; - - /* Entry into the hash table for the path + long name */ - HASHENTRY Hash; - - /* Entry into the hash table for the path + short name */ - HASHENTRY ShortHash; - - /* List of byte-range locks for this file */ - FILE_LOCK FileLock; - - /* - * Optimalization: caching of last read/write cluster+offset pair. Can't - * be in VFATCCB because it must be reset everytime the allocated clusters - * change. - */ - FAST_MUTEX LastMutex; - ULONG LastCluster; - ULONG LastOffset; -} VFATFCB, *PVFATFCB; - -typedef struct _VFATCCB -{ - LARGE_INTEGER CurrentByteOffset; - /* for DirectoryControl */ - ULONG Entry; - /* for DirectoryControl */ - UNICODE_STRING SearchPattern; -} VFATCCB, *PVFATCCB; - -#ifndef TAG -#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) -#endif - -#define TAG_CCB TAG('V', 'C', 'C', 'B') -#define TAG_FCB TAG('V', 'F', 'C', 'B') -#define TAG_IRP TAG('V', 'I', 'R', 'P') - -#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry)) - -typedef struct __DOSTIME -{ - USHORT Second:5; - USHORT Minute:6; - USHORT Hour:5; -} -DOSTIME, *PDOSTIME; - -typedef struct __DOSDATE -{ - USHORT Day:5; - USHORT Month:4; - USHORT Year:5; -} -DOSDATE, *PDOSDATE; - -#define IRPCONTEXT_CANWAIT 0x0001 -#define IRPCONTEXT_PENDINGRETURNED 0x0002 - -typedef struct -{ - PIRP Irp; - PDEVICE_OBJECT DeviceObject; - PDEVICE_EXTENSION DeviceExt; - ULONG Flags; - WORK_QUEUE_ITEM WorkQueueItem; - PIO_STACK_LOCATION Stack; - UCHAR MajorFunction; - UCHAR MinorFunction; - PFILE_OBJECT FileObject; - ULONG RefCount; - KEVENT Event; -} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT; - -typedef struct _VFAT_DIRENTRY_CONTEXT -{ - ULONG StartIndex; - ULONG DirIndex; - DIR_ENTRY DirEntry; - UNICODE_STRING LongNameU; - UNICODE_STRING ShortNameU; -} VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT; - - -/* ------------------------------------------------------ shutdown.c */ - -NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject, - PIRP Irp); - -/* -------------------------------------------------------- volume.c */ - -NTSTATUS VfatQueryVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatSetVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); - -/* ------------------------------------------------------ blockdev.c */ - -NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject, - IN PLARGE_INTEGER ReadOffset, - IN ULONG ReadLength, - IN PUCHAR Buffer, - IN BOOLEAN Override); - -NTSTATUS VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext, - IN PLARGE_INTEGER ReadOffset, - IN ULONG ReadLength, - IN ULONG BufferOffset, - IN BOOLEAN Wait); - -NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, - IN PLARGE_INTEGER WriteOffset, - IN ULONG WriteLength, - IN ULONG BufferOffset, - IN BOOLEAN Wait); - -NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, - IN ULONG CtlCode, - IN PVOID InputBuffer, - IN ULONG InputBufferSize, - IN OUT PVOID OutputBuffer, - IN OUT PULONG pOutputBufferSize, - IN BOOLEAN Override); - -/* ----------------------------------------------------------- dir.c */ - -NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT); - -BOOLEAN FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, - USHORT DosDate, - USHORT DosTime, - PLARGE_INTEGER SystemTime); - -BOOLEAN FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER SystemTime, - USHORT *pDosDate, - USHORT *pDosTime); - -/* -------------------------------------------------------- create.c */ - -NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT FileObject, - PVFATFCB* parentFcb); - -NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt, - PVFATFCB Parent, - PUNICODE_STRING FileToFindU, - PVFAT_DIRENTRY_CONTEXT DirContext, - BOOLEAN First); - -VOID vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, - PUNICODE_STRING NameU); - -NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, - PVPB Vpb); - -/* --------------------------------------------------------- close.c */ - -NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatCloseFile(PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT FileObject); - -/* ------------------------------------------------------- cleanup.c */ - -NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext); - -/* --------------------------------------------------------- fastio.c */ - -VOID -VfatInitFastIoRoutines(PFAST_IO_DISPATCH FastIoDispatch); - -BOOLEAN NTAPI -VfatAcquireForLazyWrite(IN PVOID Context, - IN BOOLEAN Wait); - -VOID NTAPI -VfatReleaseFromLazyWrite(IN PVOID Context); - -BOOLEAN NTAPI -VfatAcquireForReadAhead(IN PVOID Context, - IN BOOLEAN Wait); - -VOID NTAPI -VfatReleaseFromReadAhead(IN PVOID Context); - -/* --------------------------------------------------------- fsctl.c */ - -NTSTATUS VfatFileSystemControl (PVFAT_IRP_CONTEXT IrpContext); - -/* --------------------------------------------------------- finfo.c */ - -NTSTATUS VfatQueryInformation (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatSetInformation (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS -VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, - PVFATFCB Fcb, - PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER AllocationSize); - -/* --------------------------------------------------------- iface.c */ - -NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath); - -/* --------------------------------------------------------- dirwr.c */ - -NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt, - PUNICODE_STRING PathNameU, - PVFATFCB* Fcb, - PVFATFCB ParentFcb, - ULONG RequestedOptions, - UCHAR ReqAttr); - -NTSTATUS VfatUpdateEntry (PVFATFCB pFcb); - -NTSTATUS VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB); - -BOOLEAN -vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt, - PVFATFCB pDirFcb, - ULONG nbSlots, - PULONG start); - -/* -------------------------------------------------------- string.c */ - -VOID -vfatSplitPathName(PUNICODE_STRING PathNameU, - PUNICODE_STRING DirNameU, - PUNICODE_STRING FileNameU); - -BOOLEAN vfatIsLongIllegal(WCHAR c); - -BOOLEAN wstrcmpjoki (PWSTR s1, - PWSTR s2); - -/* ----------------------------------------------------------- fat.c */ - -NTSTATUS FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster); - -NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, - PULONG Cluster); - -NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG ClusterToWrite, - ULONG NewValue, - PULONG OldValue); - -NTSTATUS FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster); - -NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, - PULONG Cluster); - -NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG ClusterToWrite, - ULONG NewValue, - PULONG OldValue); - -NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster); - -NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, - PULONG Cluster); - -NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG ClusterToWrite, - ULONG NewValue, - PULONG OldValue); - -NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt, - ULONG FirstCluster, - ULONG FileOffset, - PULONG Cluster, - BOOLEAN Extend); - -ULONGLONG ClusterToSector (PDEVICE_EXTENSION DeviceExt, - ULONG Cluster); - -NTSTATUS GetNextCluster (PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster); - -NTSTATUS GetNextClusterExtend (PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster); - -NTSTATUS CountAvailableClusters (PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER Clusters); - -NTSTATUS -WriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG ClusterToWrite, - ULONG NewValue); - -/* ------------------------------------------------------ direntry.c */ - -ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, - PDIR_ENTRY pDirEntry); - -BOOLEAN VfatIsDirectoryEmpty(PVFATFCB Fcb); - -NTSTATUS FATGetNextDirEntry(PVOID * pContext, - PVOID * pPage, - IN PVFATFCB pDirFcb, - IN PVFAT_DIRENTRY_CONTEXT DirContext, - BOOLEAN First); - -NTSTATUS FATXGetNextDirEntry(PVOID * pContext, - PVOID * pPage, - IN PVFATFCB pDirFcb, - IN PVFAT_DIRENTRY_CONTEXT DirContext, - BOOLEAN First); - -/* ----------------------------------------------------------- fcb.c */ - -PVFATFCB vfatNewFCB (PDEVICE_EXTENSION pVCB, - PUNICODE_STRING pFileNameU); - -VOID vfatDestroyFCB (PVFATFCB pFCB); - -VOID vfatDestroyCCB(PVFATCCB pCcb); - -VOID vfatGrabFCB (PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB); - -VOID vfatReleaseFCB (PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB); - -VOID vfatAddFCBToTable (PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB); - -PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt, - PUNICODE_STRING pFileNameU); - -PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB); - -PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB); - -BOOLEAN vfatFCBIsDirectory (PVFATFCB FCB); - -BOOLEAN vfatFCBIsRoot(PVFATFCB FCB); - -NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, - PVFATFCB fcb, - PFILE_OBJECT fileObject); - -NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB, - PVFATFCB parentFCB, - PUNICODE_STRING FileToFindU, - PVFATFCB * fileFCB); - -NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, - PVFATFCB *pParentFCB, - PVFATFCB *pFCB, - PUNICODE_STRING pFileNameU); - -NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb, - PVFATFCB directoryFCB, - PVFAT_DIRENTRY_CONTEXT DirContext, - PVFATFCB * fileFCB); - -/* ------------------------------------------------------------ rw.c */ - -NTSTATUS VfatRead (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, - ULONG FirstCluster, - PULONG CurrentCluster, - BOOLEAN Extend); - -/* ----------------------------------------------------------- misc.c */ - -NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext); - -PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, - PIRP Irp); - -VOID VfatFreeIrpContext(PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS STDCALL VfatBuildRequest (PDEVICE_OBJECT DeviceObject, - PIRP Irp); - -PVOID VfatGetUserBuffer(IN PIRP); - -NTSTATUS VfatLockUserBuffer(IN PIRP, IN ULONG, - IN LOCK_OPERATION); - -NTSTATUS -VfatSetExtendedAttributes(PFILE_OBJECT FileObject, - PVOID Ea, - ULONG EaLength); -/* ------------------------------------------------------------- flush.c */ - -NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb); - - -/* EOF */ +/* $Id: vfat.h 16656 2005-07-20 02:52:52Z ion $ */ + +#include +#include +#include +#include +#include +#include +#include + +#define USE_ROS_CC_AND_FS + +#include +struct _BootSector +{ + unsigned char magic0, res0, magic1; + unsigned char OEMName[8]; + unsigned short BytesPerSector; + unsigned char SectorsPerCluster; + unsigned short ReservedSectors; + unsigned char FATCount; + unsigned short RootEntries, Sectors; + unsigned char Media; + unsigned short FATSectors, SectorsPerTrack, Heads; + unsigned long HiddenSectors, SectorsHuge; + unsigned char Drive, Res1, Sig; + unsigned long VolumeID; + unsigned char VolumeLabel[11], SysType[8]; + unsigned char Res2[448]; + unsigned short Signatur1; +}; + +struct _BootSector32 +{ + unsigned char magic0, res0, magic1; // 0 + unsigned char OEMName[8]; // 3 + unsigned short BytesPerSector; // 11 + unsigned char SectorsPerCluster; // 13 + unsigned short ReservedSectors; // 14 + unsigned char FATCount; // 16 + unsigned short RootEntries, Sectors; // 17 + unsigned char Media; // 21 + unsigned short FATSectors, SectorsPerTrack, Heads; // 22 + unsigned long HiddenSectors, SectorsHuge; // 28 + unsigned long FATSectors32; // 36 + unsigned short ExtFlag; // 40 + unsigned short FSVersion; // 42 + unsigned long RootCluster; // 44 + unsigned short FSInfoSector; // 48 + unsigned short BootBackup; // 50 + unsigned char Res3[12]; // 52 + unsigned char Drive; // 64 + unsigned char Res4; // 65 + unsigned char ExtBootSignature; // 66 + unsigned long VolumeID; // 67 + unsigned char VolumeLabel[11], SysType[8]; // 71 + unsigned char Res2[420]; // 90 + unsigned short Signature1; // 510 +}; + +struct _BootSectorFatX +{ + unsigned char SysType[4]; // 0 + unsigned long VolumeID; // 4 + unsigned long SectorsPerCluster; // 8 + unsigned short FATCount; // 12 + unsigned long Unknown; // 14 + unsigned char Unused[4078]; // 18 +}; + +struct _FsInfoSector +{ + unsigned long ExtBootSignature2; // 0 + unsigned char Res6[480]; // 4 + unsigned long FSINFOSignature; // 484 + unsigned long FreeCluster; // 488 + unsigned long NextCluster; // 492 + unsigned char Res7[12]; // 496 + unsigned long Signatur2; // 508 +}; + +typedef struct _BootSector BootSector; + +struct _FATDirEntry +{ + union + { + struct { unsigned char Filename[8], Ext[3]; }; + unsigned char ShortName[11]; + }; + unsigned char Attrib; + unsigned char lCase; + unsigned char CreationTimeMs; + unsigned short CreationTime,CreationDate,AccessDate; + unsigned short FirstClusterHigh; // higher + unsigned short UpdateTime; //time create/update + unsigned short UpdateDate; //date create/update + unsigned short FirstCluster; + unsigned long FileSize; +}; + +typedef struct _FATDirEntry FAT_DIR_ENTRY, *PFAT_DIR_ENTRY; + +struct _FATXDirEntry +{ + unsigned char FilenameLength; // 0 + unsigned char Attrib; // 1 + unsigned char Filename[42]; // 2 + unsigned long FirstCluster; // 44 + unsigned long FileSize; // 48 + unsigned short UpdateTime; // 52 + unsigned short UpdateDate; // 54 + unsigned short CreationTime; // 56 + unsigned short CreationDate; // 58 + unsigned short AccessTime; // 60 + unsigned short AccessDate; // 62 +}; + +struct _slot +{ + unsigned char id; // sequence number for slot + WCHAR name0_4[5]; // first 5 characters in name + unsigned char attr; // attribute byte + unsigned char reserved; // always 0 + unsigned char alias_checksum; // checksum for 8.3 alias + WCHAR name5_10[6]; // 6 more characters in name + unsigned char start[2]; // starting cluster number + WCHAR name11_12[2]; // last 2 characters in name +}; + +typedef struct _slot slot; + +#include + +#define VFAT_CASE_LOWER_BASE 8 // base is lower case +#define VFAT_CASE_LOWER_EXT 16 // extension is lower case + +#define LONGNAME_MAX_LENGTH 256 // max length for a long filename + +#define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat))) +#define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat))) +#define ENTRY_END(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat))) + +#define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5) +#define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0) +#define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f) +#define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08) + +#define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5) +#define FATX_ENTRY_END(DirEntry) ((DirEntry)->FilenameLength == 0xff) +#define FATX_ENTRY_LONG(DirEntry) (FALSE) +#define FATX_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08) + +#define FAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FAT_DIR_ENTRY)) +#define FATX_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATX_DIR_ENTRY)) + +typedef struct _FATXDirEntry FATX_DIR_ENTRY, *PFATX_DIR_ENTRY; + +union _DIR_ENTRY +{ + FAT_DIR_ENTRY Fat; + FATX_DIR_ENTRY FatX; +}; + +typedef union _DIR_ENTRY DIR_ENTRY, *PDIR_ENTRY; + +#define BLOCKSIZE 512 + +#define FAT16 (1) +#define FAT12 (2) +#define FAT32 (3) +#define FATX16 (4) +#define FATX32 (5) + +#define VCB_VOLUME_LOCKED 0x0001 +#define VCB_DISMOUNT_PENDING 0x0002 +#define VCB_IS_FATX 0x0004 +#define VCB_IS_DIRTY 0x4000 /* Volume is dirty */ +#define VCB_CLEAR_DIRTY 0x8000 /* Clean dirty flag at shutdown */ + +typedef struct +{ + ULONG VolumeID; + ULONG FATStart; + ULONG FATCount; + ULONG FATSectors; + ULONG rootDirectorySectors; + ULONG rootStart; + ULONG dataStart; + ULONG RootCluster; + ULONG SectorsPerCluster; + ULONG BytesPerSector; + ULONG BytesPerCluster; + ULONG NumberOfClusters; + ULONG FatType; + ULONG Sectors; + BOOLEAN FixedMedia; +} FATINFO, *PFATINFO; + +struct _VFATFCB; +struct _VFAT_DIRENTRY_CONTEXT; + +typedef struct _HASHENTRY +{ + ULONG Hash; + struct _VFATFCB* self; + struct _HASHENTRY* next; +} +HASHENTRY; + +#define FCB_HASH_TABLE_SIZE 65536 + +typedef struct DEVICE_EXTENSION *PDEVICE_EXTENSION; + +typedef NTSTATUS (*PGET_NEXT_CLUSTER)(PDEVICE_EXTENSION,ULONG,PULONG); +typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER)(PDEVICE_EXTENSION,PULONG); +typedef NTSTATUS (*PWRITE_CLUSTER)(PDEVICE_EXTENSION,ULONG,ULONG,PULONG); + +typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY)(PVOID*,PVOID*,struct _VFATFCB*,struct _VFAT_DIRENTRY_CONTEXT*,BOOLEAN); + +typedef struct DEVICE_EXTENSION +{ + ERESOURCE DirResource; + ERESOURCE FatResource; + + KSPIN_LOCK FcbListLock; + LIST_ENTRY FcbListHead; + ULONG HashTableSize; + struct _HASHENTRY** FcbHashTable; + + PDEVICE_OBJECT StorageDevice; + PFILE_OBJECT FATFileObject; + FATINFO FatInfo; + ULONG LastAvailableCluster; + ULONG AvailableClusters; + BOOLEAN AvailableClustersValid; + ULONG Flags; + struct _VFATFCB * VolumeFcb; + + /* Pointers to functions for manipulating FAT. */ + PGET_NEXT_CLUSTER GetNextCluster; + PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster; + PWRITE_CLUSTER WriteCluster; + ULONG CleanShutBitMask; + + /* Pointers to functions for manipulating directory entries. */ + PGET_NEXT_DIR_ENTRY GetNextDirEntry; + + ULONG BaseDateYear; + + LIST_ENTRY VolumeListEntry; +} DEVICE_EXTENSION, VCB, *PVCB; + +typedef struct +{ + PDRIVER_OBJECT DriverObject; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; + ERESOURCE VolumeListLock; + LIST_ENTRY VolumeListHead; + NPAGED_LOOKASIDE_LIST FcbLookasideList; + NPAGED_LOOKASIDE_LIST CcbLookasideList; + NPAGED_LOOKASIDE_LIST IrpContextLookasideList; + FAST_IO_DISPATCH FastIoDispatch; + CACHE_MANAGER_CALLBACKS CacheMgrCallbacks; +} VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA; + +extern PVFAT_GLOBAL_DATA VfatGlobalData; + +#define FCB_CACHE_INITIALIZED 0x0001 +#define FCB_DELETE_PENDING 0x0002 +#define FCB_IS_FAT 0x0004 +#define FCB_IS_PAGE_FILE 0x0008 +#define FCB_IS_VOLUME 0x0010 +#define FCB_IS_DIRTY 0x0020 +#define FCB_IS_FATX_ENTRY 0x0040 + +typedef struct _VFATFCB +{ + /* FCB header required by ROS/NT */ + FSRTL_COMMON_FCB_HEADER RFCB; + SECTION_OBJECT_POINTERS SectionObjectPointers; + ERESOURCE MainResource; + ERESOURCE PagingIoResource; + /* end FCB header required by ROS/NT */ + + /* directory entry for this file or directory */ + DIR_ENTRY entry; + + /* Pointer to attributes in entry */ + PUCHAR Attributes; + + /* long file name, points into PathNameBuffer */ + UNICODE_STRING LongNameU; + + /* short file name */ + UNICODE_STRING ShortNameU; + + /* directory name, points into PathNameBuffer */ + UNICODE_STRING DirNameU; + + /* path + long file name 260 max*/ + UNICODE_STRING PathNameU; + + /* buffer for PathNameU */ + PWCHAR PathNameBuffer; + + /* buffer for ShortNameU */ + WCHAR ShortNameBuffer[13]; + + /* */ + LONG RefCount; + + /* List of FCB's for this volume */ + LIST_ENTRY FcbListEntry; + + /* pointer to the parent fcb */ + struct _VFATFCB* parentFcb; + + /* Flags for the fcb */ + ULONG Flags; + + /* pointer to the file object which has initialized the fcb */ + PFILE_OBJECT FileObject; + + /* Directory index for the short name entry */ + ULONG dirIndex; + + /* Directory index where the long name starts */ + ULONG startIndex; + + /* Share access for the file object */ + SHARE_ACCESS FCBShareAccess; + + /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */ + ULONG OpenHandleCount; + + /* Entry into the hash table for the path + long name */ + HASHENTRY Hash; + + /* Entry into the hash table for the path + short name */ + HASHENTRY ShortHash; + + /* List of byte-range locks for this file */ + FILE_LOCK FileLock; + + /* + * Optimalization: caching of last read/write cluster+offset pair. Can't + * be in VFATCCB because it must be reset everytime the allocated clusters + * change. + */ + FAST_MUTEX LastMutex; + ULONG LastCluster; + ULONG LastOffset; +} VFATFCB, *PVFATFCB; + +typedef struct _VFATCCB +{ + LARGE_INTEGER CurrentByteOffset; + /* for DirectoryControl */ + ULONG Entry; + /* for DirectoryControl */ + UNICODE_STRING SearchPattern; +} VFATCCB, *PVFATCCB; + +#ifndef TAG +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) +#endif + +#define TAG_CCB TAG('V', 'C', 'C', 'B') +#define TAG_FCB TAG('V', 'F', 'C', 'B') +#define TAG_IRP TAG('V', 'I', 'R', 'P') + +#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry)) + +typedef struct __DOSTIME +{ + USHORT Second:5; + USHORT Minute:6; + USHORT Hour:5; +} +DOSTIME, *PDOSTIME; + +typedef struct __DOSDATE +{ + USHORT Day:5; + USHORT Month:4; + USHORT Year:5; +} +DOSDATE, *PDOSDATE; + +#define IRPCONTEXT_CANWAIT 0x0001 +#define IRPCONTEXT_PENDINGRETURNED 0x0002 + +typedef struct +{ + PIRP Irp; + PDEVICE_OBJECT DeviceObject; + PDEVICE_EXTENSION DeviceExt; + ULONG Flags; + WORK_QUEUE_ITEM WorkQueueItem; + PIO_STACK_LOCATION Stack; + UCHAR MajorFunction; + UCHAR MinorFunction; + PFILE_OBJECT FileObject; + ULONG RefCount; + KEVENT Event; +} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT; + +typedef struct _VFAT_DIRENTRY_CONTEXT +{ + ULONG StartIndex; + ULONG DirIndex; + DIR_ENTRY DirEntry; + UNICODE_STRING LongNameU; + UNICODE_STRING ShortNameU; +} VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT; + + +/* ------------------------------------------------------ shutdown.c */ + +NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* -------------------------------------------------------- volume.c */ + +NTSTATUS VfatQueryVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatSetVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); + +/* ------------------------------------------------------ blockdev.c */ + +NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject, + IN PLARGE_INTEGER ReadOffset, + IN ULONG ReadLength, + IN PUCHAR Buffer, + IN BOOLEAN Override); + +NTSTATUS VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext, + IN PLARGE_INTEGER ReadOffset, + IN ULONG ReadLength, + IN ULONG BufferOffset, + IN BOOLEAN Wait); + +NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, + IN PLARGE_INTEGER WriteOffset, + IN ULONG WriteLength, + IN ULONG BufferOffset, + IN BOOLEAN Wait); + +NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, + IN ULONG CtlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG pOutputBufferSize, + IN BOOLEAN Override); + +/* ----------------------------------------------------------- dir.c */ + +NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT); + +BOOLEAN FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, + USHORT DosDate, + USHORT DosTime, + PLARGE_INTEGER SystemTime); + +BOOLEAN FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER SystemTime, + USHORT *pDosDate, + USHORT *pDosTime); + +/* -------------------------------------------------------- create.c */ + +NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVFATFCB* parentFcb); + +NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt, + PVFATFCB Parent, + PUNICODE_STRING FileToFindU, + PVFAT_DIRENTRY_CONTEXT DirContext, + BOOLEAN First); + +VOID vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, + PUNICODE_STRING NameU); + +NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, + PVPB Vpb); + +/* --------------------------------------------------------- close.c */ + +NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatCloseFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject); + +/* ------------------------------------------------------- cleanup.c */ + +NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext); + +/* --------------------------------------------------------- fastio.c */ + +VOID +VfatInitFastIoRoutines(PFAST_IO_DISPATCH FastIoDispatch); + +BOOLEAN NTAPI +VfatAcquireForLazyWrite(IN PVOID Context, + IN BOOLEAN Wait); + +VOID NTAPI +VfatReleaseFromLazyWrite(IN PVOID Context); + +BOOLEAN NTAPI +VfatAcquireForReadAhead(IN PVOID Context, + IN BOOLEAN Wait); + +VOID NTAPI +VfatReleaseFromReadAhead(IN PVOID Context); + +/* --------------------------------------------------------- fsctl.c */ + +NTSTATUS VfatFileSystemControl (PVFAT_IRP_CONTEXT IrpContext); + +/* --------------------------------------------------------- finfo.c */ + +NTSTATUS VfatQueryInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatSetInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS +VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, + PVFATFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER AllocationSize); + +/* --------------------------------------------------------- iface.c */ + +NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath); + +/* --------------------------------------------------------- dirwr.c */ + +NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt, + PUNICODE_STRING PathNameU, + PVFATFCB* Fcb, + PVFATFCB ParentFcb, + ULONG RequestedOptions, + UCHAR ReqAttr); + +NTSTATUS VfatUpdateEntry (PVFATFCB pFcb); + +NTSTATUS VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB); + +BOOLEAN +vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt, + PVFATFCB pDirFcb, + ULONG nbSlots, + PULONG start); + +/* -------------------------------------------------------- string.c */ + +VOID +vfatSplitPathName(PUNICODE_STRING PathNameU, + PUNICODE_STRING DirNameU, + PUNICODE_STRING FileNameU); + +BOOLEAN vfatIsLongIllegal(WCHAR c); + +BOOLEAN wstrcmpjoki (PWSTR s1, + PWSTR s2); + +/* ----------------------------------------------------------- fat.c */ + +NTSTATUS FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster); + +NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, + PULONG Cluster); + +NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue, + PULONG OldValue); + +NTSTATUS FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster); + +NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, + PULONG Cluster); + +NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue, + PULONG OldValue); + +NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster); + +NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, + PULONG Cluster); + +NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue, + PULONG OldValue); + +NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt, + ULONG FirstCluster, + ULONG FileOffset, + PULONG Cluster, + BOOLEAN Extend); + +ULONGLONG ClusterToSector (PDEVICE_EXTENSION DeviceExt, + ULONG Cluster); + +NTSTATUS GetNextCluster (PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster); + +NTSTATUS GetNextClusterExtend (PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster); + +NTSTATUS CountAvailableClusters (PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER Clusters); + +NTSTATUS +WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue); + +/* ------------------------------------------------------ direntry.c */ + +ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, + PDIR_ENTRY pDirEntry); + +BOOLEAN VfatIsDirectoryEmpty(PVFATFCB Fcb); + +NTSTATUS FATGetNextDirEntry(PVOID * pContext, + PVOID * pPage, + IN PVFATFCB pDirFcb, + IN PVFAT_DIRENTRY_CONTEXT DirContext, + BOOLEAN First); + +NTSTATUS FATXGetNextDirEntry(PVOID * pContext, + PVOID * pPage, + IN PVFATFCB pDirFcb, + IN PVFAT_DIRENTRY_CONTEXT DirContext, + BOOLEAN First); + +/* ----------------------------------------------------------- fcb.c */ + +PVFATFCB vfatNewFCB (PDEVICE_EXTENSION pVCB, + PUNICODE_STRING pFileNameU); + +VOID vfatDestroyFCB (PVFATFCB pFCB); + +VOID vfatDestroyCCB(PVFATCCB pCcb); + +VOID vfatGrabFCB (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +VOID vfatReleaseFCB (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +VOID vfatAddFCBToTable (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt, + PUNICODE_STRING pFileNameU); + +PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB); + +PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB); + +BOOLEAN vfatFCBIsDirectory (PVFATFCB FCB); + +BOOLEAN vfatFCBIsRoot(PVFATFCB FCB); + +NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, + PVFATFCB fcb, + PFILE_OBJECT fileObject); + +NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB, + PVFATFCB parentFCB, + PUNICODE_STRING FileToFindU, + PVFATFCB * fileFCB); + +NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, + PVFATFCB *pParentFCB, + PVFATFCB *pFCB, + PUNICODE_STRING pFileNameU); + +NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb, + PVFATFCB directoryFCB, + PVFAT_DIRENTRY_CONTEXT DirContext, + PVFATFCB * fileFCB); + +/* ------------------------------------------------------------ rw.c */ + +NTSTATUS VfatRead (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG FirstCluster, + PULONG CurrentCluster, + BOOLEAN Extend); + +/* ----------------------------------------------------------- misc.c */ + +NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext); + +PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +VOID VfatFreeIrpContext(PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS STDCALL VfatBuildRequest (PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +PVOID VfatGetUserBuffer(IN PIRP); + +NTSTATUS VfatLockUserBuffer(IN PIRP, IN ULONG, + IN LOCK_OPERATION); + +NTSTATUS +VfatSetExtendedAttributes(PFILE_OBJECT FileObject, + PVOID Ea, + ULONG EaLength); +/* ------------------------------------------------------------- flush.c */ + +NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb); + + +/* EOF */ diff --git a/rosapps/sysutils/mkdosfs/mkdosfs.c b/rosapps/sysutils/mkdosfs/mkdosfs.c index 9c6e0ed82f3..ab126c5ea5e 100644 --- a/rosapps/sysutils/mkdosfs/mkdosfs.c +++ b/rosapps/sysutils/mkdosfs/mkdosfs.c @@ -24,9 +24,9 @@ - New options -A, -S, -C - Support for filesystems > 2GB - FAT32 support - - Port to work under Windows NT/2K/XP Dec 2002 by - Jens-Uwe Mager + + Port to work under Windows NT/2K/XP Dec 2002 by + Jens-Uwe Mager Copying: Copyright 1993, 1994 David Hudson (dave@humbug.demon.co.uk) @@ -51,34 +51,34 @@ /* Include the header files */ #include "../version.h" - -#ifdef _WIN32 -#define _WIN32_WINNT 0x0400 -#include -#include -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#define __BYTE_ORDER __LITTLE_ENDIAN -#define inline -#define __attribute__(x) -#define BLOCK_SIZE 512 + +#ifdef _WIN32 +#define _WIN32_WINNT 0x0400 +#include +#include +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __BYTE_ORDER __LITTLE_ENDIAN +#define inline +#define __attribute__(x) +#define BLOCK_SIZE 512 #else #include #include #include #include #include -#include -#include -#include +#include +#include +#include #endif -#include +#include #include #include #include #include #include -#include +#include #if __BYTE_ORDER == __BIG_ENDIAN @@ -106,202 +106,202 @@ #define CT_LE_L(v) (v) #endif /* __BIG_ENDIAN */ - -#ifdef _WIN32 - -typedef unsigned char __u8; -typedef unsigned short __u16; -typedef unsigned int __u32; -typedef unsigned __int64 __u64; -typedef __int64 loff_t; -typedef __int64 ll_t; - -extern char *optarg; -extern int optind; -extern int opterr; -extern int optopt; -int getopt(int argc, char *const argv[], const char * optstring); - -static int is_device = 0; - -#define open WIN32open -#define close WIN32close -#define read WIN32read -#define write WIN32write -#define llseek WIN32llseek - -#define O_SHORT_LIVED _O_SHORT_LIVED -#define O_ACCMODE 3 -#define O_NONE 3 -#define O_BACKUP 0x10000 -#define O_SHARED 0x20000 - -static int WIN32open(const char *path, int oflag, ...) -{ - HANDLE fh; - DWORD desiredAccess; - DWORD shareMode; - DWORD creationDisposition; - DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL; - SECURITY_ATTRIBUTES securityAttributes; - va_list ap; - int pmode; - int trunc = FALSE; - - securityAttributes.nLength = sizeof(securityAttributes); - securityAttributes.lpSecurityDescriptor = NULL; - securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE; - switch (oflag & O_ACCMODE) { - case O_RDONLY: - desiredAccess = GENERIC_READ; - shareMode = FILE_SHARE_READ; - break; - case O_WRONLY: - desiredAccess = GENERIC_WRITE; - shareMode = 0; - break; - case O_RDWR: - desiredAccess = GENERIC_READ|GENERIC_WRITE; - shareMode = 0; - break; - case O_NONE: - desiredAccess = 0; - shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; - } - if (oflag & O_APPEND) { - desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE; - shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; - } - if (oflag & O_SHARED) - shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE; - switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) { - case 0: - case O_EXCL: - creationDisposition = OPEN_EXISTING; - break; - case O_CREAT: - creationDisposition = OPEN_ALWAYS; - break; - case O_CREAT|O_EXCL: - case O_CREAT|O_TRUNC|O_EXCL: - creationDisposition = CREATE_NEW; - break; - case O_TRUNC: - case O_TRUNC|O_EXCL: - creationDisposition = TRUNCATE_EXISTING; - break; - case O_CREAT|O_TRUNC: - creationDisposition = OPEN_ALWAYS; - trunc = TRUE; - break; - } - if (oflag & O_CREAT) { - va_start(ap, oflag); - pmode = va_arg(ap, int); - va_end(ap); - if ((pmode & 0222) == 0) - flagsAttributes |= FILE_ATTRIBUTE_READONLY; - } - if (oflag & O_TEMPORARY) { - flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE; - desiredAccess |= DELETE; - } - if (oflag & O_SHORT_LIVED) - flagsAttributes |= FILE_ATTRIBUTE_TEMPORARY; - if (oflag & O_SEQUENTIAL) - flagsAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; - else if (oflag & O_RANDOM) - flagsAttributes |= FILE_FLAG_RANDOM_ACCESS; - if (oflag & O_BACKUP) - flagsAttributes |= FILE_FLAG_BACKUP_SEMANTICS; - if ((fh = CreateFile(path, desiredAccess, shareMode, &securityAttributes, - creationDisposition, flagsAttributes, NULL)) == INVALID_HANDLE_VALUE) { - errno = GetLastError(); - return -1; - } - if (trunc) { - if (!SetEndOfFile(fh)) { - errno = GetLastError(); - CloseHandle(fh); - DeleteFile(path); - return -1; - } - } - return (int)fh; -} - -static int WIN32close(int fd) -{ - if (!CloseHandle((HANDLE)fd)) { - errno = GetLastError(); - return -1; - } - return 0; -} - -static int WIN32read(int fd, void *buf, unsigned int len) -{ - DWORD actualLen; - - if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) { - errno = GetLastError(); - if (errno == ERROR_BROKEN_PIPE) - return 0; - else - return -1; - } - return (int)actualLen; -} - -static int WIN32write(int fd, void *buf, unsigned int len) -{ - DWORD actualLen; - - if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) { - errno = GetLastError(); - return -1; - } - return (int)actualLen; -} - -static loff_t WIN32llseek(int fd, loff_t offset, int whence) -{ - long lo, hi; - DWORD err; - - lo = offset & 0xffffffff; - hi = offset >> 32; - lo = SetFilePointer((HANDLE)fd, lo, &hi, whence); - if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) { - errno = err; - return -1; - } - return ((loff_t)hi << 32) | (off_t)lo; -} - -int fsctl(int fd, int code) -{ - DWORD ret; - if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) { - errno = GetLastError(); - return -1; - } - return 0; -} - -#else - -#define O_NOINHERIT 0 -#define O_TEMPORARY 0 -#define O_SHORT_LIVED 0 -#define O_SEQUENTIAL 0 -#define O_RANDOM 0 -#define O_BACKUP 0 -#define O_SHARED 0 -#ifndef O_NONE -# define O_NONE 0 -#endif - + +#ifdef _WIN32 + +typedef unsigned char __u8; +typedef unsigned short __u16; +typedef unsigned int __u32; +typedef unsigned __int64 __u64; +typedef __int64 loff_t; +typedef __int64 ll_t; + +extern char *optarg; +extern int optind; +extern int opterr; +extern int optopt; +int getopt(int argc, char *const argv[], const char * optstring); + +static int is_device = 0; + +#define open WIN32open +#define close WIN32close +#define read WIN32read +#define write WIN32write +#define llseek WIN32llseek + +#define O_SHORT_LIVED _O_SHORT_LIVED +#define O_ACCMODE 3 +#define O_NONE 3 +#define O_BACKUP 0x10000 +#define O_SHARED 0x20000 + +static int WIN32open(const char *path, int oflag, ...) +{ + HANDLE fh; + DWORD desiredAccess; + DWORD shareMode; + DWORD creationDisposition; + DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL; + SECURITY_ATTRIBUTES securityAttributes; + va_list ap; + int pmode; + int trunc = FALSE; + + securityAttributes.nLength = sizeof(securityAttributes); + securityAttributes.lpSecurityDescriptor = NULL; + securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE; + switch (oflag & O_ACCMODE) { + case O_RDONLY: + desiredAccess = GENERIC_READ; + shareMode = FILE_SHARE_READ; + break; + case O_WRONLY: + desiredAccess = GENERIC_WRITE; + shareMode = 0; + break; + case O_RDWR: + desiredAccess = GENERIC_READ|GENERIC_WRITE; + shareMode = 0; + break; + case O_NONE: + desiredAccess = 0; + shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; + } + if (oflag & O_APPEND) { + desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE; + shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; + } + if (oflag & O_SHARED) + shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE; + switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) { + case 0: + case O_EXCL: + creationDisposition = OPEN_EXISTING; + break; + case O_CREAT: + creationDisposition = OPEN_ALWAYS; + break; + case O_CREAT|O_EXCL: + case O_CREAT|O_TRUNC|O_EXCL: + creationDisposition = CREATE_NEW; + break; + case O_TRUNC: + case O_TRUNC|O_EXCL: + creationDisposition = TRUNCATE_EXISTING; + break; + case O_CREAT|O_TRUNC: + creationDisposition = OPEN_ALWAYS; + trunc = TRUE; + break; + } + if (oflag & O_CREAT) { + va_start(ap, oflag); + pmode = va_arg(ap, int); + va_end(ap); + if ((pmode & 0222) == 0) + flagsAttributes |= FILE_ATTRIBUTE_READONLY; + } + if (oflag & O_TEMPORARY) { + flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + desiredAccess |= DELETE; + } + if (oflag & O_SHORT_LIVED) + flagsAttributes |= FILE_ATTRIBUTE_TEMPORARY; + if (oflag & O_SEQUENTIAL) + flagsAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; + else if (oflag & O_RANDOM) + flagsAttributes |= FILE_FLAG_RANDOM_ACCESS; + if (oflag & O_BACKUP) + flagsAttributes |= FILE_FLAG_BACKUP_SEMANTICS; + if ((fh = CreateFile(path, desiredAccess, shareMode, &securityAttributes, + creationDisposition, flagsAttributes, NULL)) == INVALID_HANDLE_VALUE) { + errno = GetLastError(); + return -1; + } + if (trunc) { + if (!SetEndOfFile(fh)) { + errno = GetLastError(); + CloseHandle(fh); + DeleteFile(path); + return -1; + } + } + return (int)fh; +} + +static int WIN32close(int fd) +{ + if (!CloseHandle((HANDLE)fd)) { + errno = GetLastError(); + return -1; + } + return 0; +} + +static int WIN32read(int fd, void *buf, unsigned int len) +{ + DWORD actualLen; + + if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) { + errno = GetLastError(); + if (errno == ERROR_BROKEN_PIPE) + return 0; + else + return -1; + } + return (int)actualLen; +} + +static int WIN32write(int fd, void *buf, unsigned int len) +{ + DWORD actualLen; + + if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) { + errno = GetLastError(); + return -1; + } + return (int)actualLen; +} + +static loff_t WIN32llseek(int fd, loff_t offset, int whence) +{ + long lo, hi; + DWORD err; + + lo = offset & 0xffffffff; + hi = offset >> 32; + lo = SetFilePointer((HANDLE)fd, lo, &hi, whence); + if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) { + errno = err; + return -1; + } + return ((loff_t)hi << 32) | (off_t)lo; +} + +int fsctl(int fd, int code) +{ + DWORD ret; + if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) { + errno = GetLastError(); + return -1; + } + return 0; +} + +#else + +#define O_NOINHERIT 0 +#define O_TEMPORARY 0 +#define O_SHORT_LIVED 0 +#define O_SEQUENTIAL 0 +#define O_RANDOM 0 +#define O_BACKUP 0 +#define O_SHARED 0 +#ifndef O_NONE +# define O_NONE 0 +#endif + typedef long long ll_t; /* Use the _llseek system call directly, because there (once?) was a bug in * the glibc implementation of it. */ @@ -327,8 +327,8 @@ static loff_t llseek( int fd, loff_t offset, int whence ) return actual; } #endif - -#endif + +#endif /* Constant definitions */ @@ -402,9 +402,9 @@ cdiv (int a, int b) /* __attribute__ ((packed)) is used on all structures to make gcc ignore any * alignments */ - -#ifdef _WIN32 -#pragma pack(push, 1) + +#ifdef _WIN32 +#pragma pack(push, 1) #endif struct msdos_volume_info { __u8 drive_number; /* BIOS drive number */ @@ -476,10 +476,10 @@ struct msdos_dir_entry __u16 time, date, start; /* time, date and first cluster */ __u32 size; /* file size (in bytes) */ } __attribute__ ((packed)); - -#ifdef _WIN32 -#pragma pack(pop) -#endif + +#ifdef _WIN32 +#pragma pack(pop) +#endif /* The "boot code" we put into the filesystem... it writes a message and tells the user to try again */ @@ -559,12 +559,12 @@ static void check_blocks (void); static void get_list_blocks (char *filename); static int valid_offset (int fd, loff_t offset); static int count_blocks (char *filename); -static void check_mount (char *device_name); -#ifdef _WIN32 -static void establish_params (void); +static void check_mount (char *device_name); +#ifdef _WIN32 +static void establish_params (void); #else static void establish_params (int device_num, int size); -#endif +#endif static void setup_tables (void); static void write_tables (void); @@ -692,13 +692,13 @@ check_blocks (void) printf ("Searching for bad blocks "); fflush (stdout); } - currently_testing = 0; + currently_testing = 0; #ifndef _WIN32 if (verbose) { signal (SIGALRM, alarm_intr); alarm (5); - } + } #endif try = TEST_BUFFER_BLOCKS; while (currently_testing < blocks) @@ -757,7 +757,7 @@ get_list_blocks (char *filename) (badblocks > 1) ? "s" : ""); } - + #ifndef _WIN32 /* Given a file descriptor and an offset, check whether the offset is a valid offset for the file - return FALSE if it isn't valid or TRUE if it is */ @@ -773,44 +773,44 @@ valid_offset (int fd, loff_t offset) return FALSE; return TRUE; } -#endif +#endif /* Given a filename, look to see how many blocks of BLOCK_SIZE are present, returning the answer */ static int count_blocks (char *filename) -{ -#ifdef _WIN32 - int fd; - DISK_GEOMETRY geom; - BY_HANDLE_FILE_INFORMATION hinfo; - DWORD ret; - loff_t len = 0; - - if ((fd = open(filename, O_RDONLY)) < 0) { - perror(filename); - exit(1); - } - /* - * This should probably use IOCTL_DISK_GET_LENGTH_INFO here, but - * this ioctl is only available in XP and up. - */ - if (is_device) { - if (!DeviceIoControl((HANDLE)fd, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geom, sizeof(geom), &ret, NULL)) { - errno = GetLastError(); - die("unable to get length for '%s'"); - } - len = geom.Cylinders.QuadPart*geom.TracksPerCylinder*geom.SectorsPerTrack*BLOCK_SIZE; - } else { - if (!GetFileInformationByHandle((HANDLE)fd, &hinfo)) { - errno = GetLastError(); - die("unable to get length for '%s'"); - } - len = ((loff_t)hinfo.nFileSizeHigh << 32) | (loff_t)hinfo.nFileSizeLow; - } - close(fd); - return len/BLOCK_SIZE; +{ +#ifdef _WIN32 + int fd; + DISK_GEOMETRY geom; + BY_HANDLE_FILE_INFORMATION hinfo; + DWORD ret; + loff_t len = 0; + + if ((fd = open(filename, O_RDONLY)) < 0) { + perror(filename); + exit(1); + } + /* + * This should probably use IOCTL_DISK_GET_LENGTH_INFO here, but + * this ioctl is only available in XP and up. + */ + if (is_device) { + if (!DeviceIoControl((HANDLE)fd, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geom, sizeof(geom), &ret, NULL)) { + errno = GetLastError(); + die("unable to get length for '%s'"); + } + len = geom.Cylinders.QuadPart*geom.TracksPerCylinder*geom.SectorsPerTrack*BLOCK_SIZE; + } else { + if (!GetFileInformationByHandle((HANDLE)fd, &hinfo)) { + errno = GetLastError(); + die("unable to get length for '%s'"); + } + len = ((loff_t)hinfo.nFileSizeHigh << 32) | (loff_t)hinfo.nFileSizeLow; + } + close(fd); + return len/BLOCK_SIZE; #else loff_t high, low; int fd; @@ -836,7 +836,7 @@ count_blocks (char *filename) valid_offset (fd, 0); close (fd); - return (low + 1) / BLOCK_SIZE; + return (low + 1) / BLOCK_SIZE; #endif } @@ -845,7 +845,7 @@ count_blocks (char *filename) static void check_mount (char *device_name) -{ +{ #ifndef _WIN32 FILE *f; struct mntent *mnt; @@ -855,70 +855,70 @@ check_mount (char *device_name) while ((mnt = getmntent (f)) != NULL) if (strcmp (device_name, mnt->mnt_fsname) == 0) die ("%s contains a mounted file system."); - endmntent (f); + endmntent (f); #endif } /* Establish the geometry and media parameters for the device */ -#ifdef _WIN32 -static void -establish_params (void) -{ - DISK_GEOMETRY geometry; - DWORD ret; - - if (!is_device) { - bs.media = (char) 0xf8; /* Set up the media descriptor for a hard drive */ - bs.dir_entries[0] = (char) 0; - bs.dir_entries[1] = (char) 2; - /* For FAT32, use 4k clusters on sufficiently large file systems, - * otherwise 1 sector per cluster. This is also what M$'s format - * command does for FAT32. */ - bs.cluster_size = (char) - (size_fat == 32 ? - ((ll_t)blocks*SECTORS_PER_BLOCK >= 512*1024 ? 8 : 1) : - 4); /* FAT12 and FAT16: start at 4 sectors per cluster */ - return; - } - if (!DeviceIoControl((HANDLE)dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geometry, sizeof(geometry), &ret, NULL)) { - errno = GetLastError(); - die ("unable to get geometry for '%s'"); - } - bs.secs_track = geometry.SectorsPerTrack; - bs.heads = geometry.TracksPerCylinder; - switch (geometry.MediaType) { - case F3_1Pt44_512: - bs.media = (char) 0xf9; - bs.cluster_size = (char) 2; - bs.dir_entries[0] = (char) 112; - bs.dir_entries[1] = (char) 0; - break; - case F3_2Pt88_512: - bs.media = (char) 0xf0; - bs.cluster_size = (char)(atari_format ? 2 : 1); - bs.dir_entries[0] = (char) 224; - bs.dir_entries[1] = (char) 0; - break; - case F3_720_512: - bs.media = (char) 0xfd; - bs.cluster_size = (char) 2; - bs.dir_entries[0] = (char) 112; - bs.dir_entries[1] = (char) 0; - break; - default: - bs.media = (char) 0xf8; /* Set up the media descriptor for a hard drive */ - bs.dir_entries[0] = (char) 0; - bs.dir_entries[1] = (char) 2; - /* For FAT32, use 4k clusters on sufficiently large file systems, - * otherwise 1 sector per cluster. This is also what M$'s format - * command does for FAT32. */ - bs.cluster_size = (char) - (size_fat == 32 ? - ((ll_t)blocks*SECTORS_PER_BLOCK >= 512*1024 ? 8 : 1) : - 4); /* FAT12 and FAT16: start at 4 sectors per cluster */ - } -} +#ifdef _WIN32 +static void +establish_params (void) +{ + DISK_GEOMETRY geometry; + DWORD ret; + + if (!is_device) { + bs.media = (char) 0xf8; /* Set up the media descriptor for a hard drive */ + bs.dir_entries[0] = (char) 0; + bs.dir_entries[1] = (char) 2; + /* For FAT32, use 4k clusters on sufficiently large file systems, + * otherwise 1 sector per cluster. This is also what M$'s format + * command does for FAT32. */ + bs.cluster_size = (char) + (size_fat == 32 ? + ((ll_t)blocks*SECTORS_PER_BLOCK >= 512*1024 ? 8 : 1) : + 4); /* FAT12 and FAT16: start at 4 sectors per cluster */ + return; + } + if (!DeviceIoControl((HANDLE)dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geometry, sizeof(geometry), &ret, NULL)) { + errno = GetLastError(); + die ("unable to get geometry for '%s'"); + } + bs.secs_track = geometry.SectorsPerTrack; + bs.heads = geometry.TracksPerCylinder; + switch (geometry.MediaType) { + case F3_1Pt44_512: + bs.media = (char) 0xf9; + bs.cluster_size = (char) 2; + bs.dir_entries[0] = (char) 112; + bs.dir_entries[1] = (char) 0; + break; + case F3_2Pt88_512: + bs.media = (char) 0xf0; + bs.cluster_size = (char)(atari_format ? 2 : 1); + bs.dir_entries[0] = (char) 224; + bs.dir_entries[1] = (char) 0; + break; + case F3_720_512: + bs.media = (char) 0xfd; + bs.cluster_size = (char) 2; + bs.dir_entries[0] = (char) 112; + bs.dir_entries[1] = (char) 0; + break; + default: + bs.media = (char) 0xf8; /* Set up the media descriptor for a hard drive */ + bs.dir_entries[0] = (char) 0; + bs.dir_entries[1] = (char) 2; + /* For FAT32, use 4k clusters on sufficiently large file systems, + * otherwise 1 sector per cluster. This is also what M$'s format + * command does for FAT32. */ + bs.cluster_size = (char) + (size_fat == 32 ? + ((ll_t)blocks*SECTORS_PER_BLOCK >= 512*1024 ? 8 : 1) : + 4); /* FAT12 and FAT16: start at 4 sectors per cluster */ + } +} #else static void establish_params (int device_num,int size) @@ -1099,7 +1099,7 @@ establish_params (int device_num,int size) 4); /* FAT12 and FAT16: start at 4 sectors per cluster */ } } -#endif +#endif /* Create the filesystem data tables */ @@ -1629,9 +1629,9 @@ static void write_tables (void) { int x; - int fat_length; -#ifdef _WIN32 - int blk; + int fat_length; +#ifdef _WIN32 + int blk; #endif fat_length = (size_fat == 32) ? @@ -1658,17 +1658,17 @@ write_tables (void) } /* seek to start of FATS and write them all */ seekto( reserved_sectors*sector_size, "first FAT" ); - for (x = 1; x <= nr_fats; x++) -#ifdef _WIN32 - /* - * WIN32 appearently has problems writing very large chunks directly - * to disk devices. To not produce errors because of resource shortages - * split up the write in sector size chunks. - */ - for (blk = 0; blk < fat_length; blk++) - writebuf(fat+blk*sector_size, sector_size, "FAT"); + for (x = 1; x <= nr_fats; x++) +#ifdef _WIN32 + /* + * WIN32 appearently has problems writing very large chunks directly + * to disk devices. To not produce errors because of resource shortages + * split up the write in sector size chunks. + */ + for (blk = 0; blk < fat_length; blk++) + writebuf(fat+blk*sector_size, sector_size, "FAT"); #else - writebuf( fat, fat_length * sector_size, "FAT" ); + writebuf( fat, fat_length * sector_size, "FAT" ); #endif /* Write the root directory directly after the last FAT. This is the root * dir area on FAT12/16, and the first cluster on FAT32. */ @@ -1730,22 +1730,22 @@ main (int argc, char **argv) int c; char *tmp; char *listfile = NULL; - FILE *msgfile; -#ifdef _WIN32 - static char dev_buf[] = "\\\\.\\X:"; + FILE *msgfile; +#ifdef _WIN32 + static char dev_buf[] = "\\\\.\\X:"; #else - struct stat statbuf; + struct stat statbuf; #endif int i = 0, pos, ch; int create = 0; if (argc && *argv) { /* What's the program name? */ char *p; - program_name = *argv; -#ifdef _WIN32 - if ((p = strrchr( program_name, '\\' ))) + program_name = *argv; +#ifdef _WIN32 + if ((p = strrchr( program_name, '\\' ))) #else - if ((p = strrchr( program_name, '/' ))) + if ((p = strrchr( program_name, '/' ))) #endif program_name = p+1; } @@ -1754,9 +1754,9 @@ main (int argc, char **argv) volume_id = (long)create_time; /* Default volume ID = creation time */ check_atari(); - printf ("%s " VERSION " (" VERSION_DATE ")\n" -#ifdef _WIN32 - "Win32 port by Jens-Uwe Mager \n" + printf ("%s " VERSION " (" VERSION_DATE ")\n" +#ifdef _WIN32 + "Win32 port by Jens-Uwe Mager \n" #endif , program_name); @@ -1943,16 +1943,16 @@ main (int argc, char **argv) printf( "Unknown option: %c\n", c ); usage (); } - - if (optind >= argc) + + if (optind >= argc) usage(); - device_name = argv[optind]; /* Determine the number of blocks in the FS */ -#ifdef _WIN32 - if (device_name[1] == ':' && device_name[2] == '\0') { - dev_buf[4] = device_name[0]; - device_name = dev_buf; - is_device = 1; - } + device_name = argv[optind]; /* Determine the number of blocks in the FS */ +#ifdef _WIN32 + if (device_name[1] == ':' && device_name[2] == '\0') { + dev_buf[4] = device_name[0]; + device_name = dev_buf; + is_device = 1; + } #endif if (!create) i = count_blocks (device_name); /* Have a look and see! */ @@ -1987,12 +1987,12 @@ main (int argc, char **argv) check_mount (device_name); /* Is the device already mounted? */ dev = open (device_name, O_RDWR|O_SHARED); /* Is it a suitable device to build the FS on? */ if (dev < 0) - die ("unable to open %s"); -#ifdef _WIN32 - if (is_device) { - if (fsctl(dev, FSCTL_LOCK_VOLUME) == -1) - die("unable to lock %s"); - } + die ("unable to open %s"); +#ifdef _WIN32 + if (is_device) { + if (fsctl(dev, FSCTL_LOCK_VOLUME) == -1) + die("unable to lock %s"); + } #endif } else { @@ -2011,11 +2011,11 @@ main (int argc, char **argv) if (llseek( dev, 0, SEEK_SET ) != 0) die( "seek failed" ); } - -#ifdef _WIN32 - if (!is_device) - check = 0; - establish_params(); + +#ifdef _WIN32 + if (!is_device) + check = 0; + establish_params(); #else if (fstat (dev, &statbuf) < 0) die ("unable to stat %s"); @@ -2040,7 +2040,7 @@ main (int argc, char **argv) die ("Will not try to make filesystem on '%s'"); establish_params (statbuf.st_rdev,statbuf.st_size); - /* Establish the media parameters */ + /* Establish the media parameters */ #endif setup_tables (); /* Establish the file system tables */ @@ -2052,14 +2052,14 @@ main (int argc, char **argv) write_tables (); /* Write the file system tables away! */ -#ifdef _WIN32 - if (is_device) { - if (fsctl(dev, FSCTL_DISMOUNT_VOLUME) == -1) - die("unable to dismount %s"); - if (fsctl(dev, FSCTL_UNLOCK_VOLUME) == -1) - die("unable to unlock %s"); - } -#endif +#ifdef _WIN32 + if (is_device) { + if (fsctl(dev, FSCTL_DISMOUNT_VOLUME) == -1) + die("unable to dismount %s"); + if (fsctl(dev, FSCTL_UNLOCK_VOLUME) == -1) + die("unable to unlock %s"); + } +#endif exit (0); /* Terminate with no errors! */ }