//***************************************************************************** WSTRING CFileDialogWidget::GetSelectedFileName() const //Returns: the full file name { WSTRING filename = this->dirpath; filename += wszSlash; filename += this->pFilenameTextBox->GetText(); //Add extension if it's missing. WSTRING ext; UINT i; for (i=0; i<pExtensionListBoxWidget->GetItemCount(); ++i) { ext = wszPeriod; ext += this->extensions[pExtensionListBoxWidget->GetKeyAtLine(i)]; if (!WCSicmp(filename.c_str() + WCSlen(filename.c_str()) - ext.size(), ext.c_str())) break; } if (i==pExtensionListBoxWidget->GetItemCount()) { //Extension is missing. Add the selected one. ext = wszPeriod; ext += this->extensions[pExtensionListBoxWidget->GetSelectedItem()]; filename += ext.c_str(); } return filename; }
//***************************************************************************** void CFileDialogWidget::GoToDirectory() //Go to selected directory. { const WSTRING wstrDirname = this->pDirListBoxWidget->GetSelectedItemText(); if (wstrDirname.empty()) return; //nothing is selected if (!WCScmp(wszParentDir,wstrDirname.c_str())) { //Go up a directory. const int nSlashLoc=this->dirpath.rfind(wszSlash); if (nSlashLoc<0) this->dirpath.resize(0); #ifndef WIN32 else if (nSlashLoc == 0) this->dirpath.resize(1); // go to root dir #endif else this->dirpath.resize(nSlashLoc); #if defined(WIN32) || defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__native_client__) } else if (wstrDirname[0] == W_t('[')) { //Switch drives. WSTRING newDrive = wstrDirname.c_str() + 2; newDrive.resize(newDrive.size()-2); SetDirectory(newDrive.c_str()); return; #endif } else { //Go down a directory. if (this->dirpath.c_str() && (this->dirpath.c_str()[this->dirpath.length()-1] != wszSlash[0])) this->dirpath += wszSlash; this->dirpath += wstrDirname; } SetDirectory(); }
//****************************************************************************** bool CClipboard::SetString( //Copies the given string into the system clipboard //Returns: true on success, false otherwise. // //Params: const WSTRING& sClip) //(in) { #ifdef WIN32 if (!OpenClipboard(NULL)) return false; EmptyClipboard(); HGLOBAL global = GlobalAlloc(GMEM_ZEROINIT, (sClip.size()+1)*sizeof(WCHAR)); if (global == NULL) { CloseClipboard(); return false; } LPWSTR data = (LPWSTR)GlobalLock(global); WCScpy(data, sClip.c_str()); GlobalUnlock(global); SetClipboardData(CF_UNICODETEXT, global); CloseClipboard(); return true; #elif defined(__APPLE__) PasteboardRef theClipboard; OSStatus err = PasteboardCreate(kPasteboardClipboard, &theClipboard); if (err != noErr) return false; PasteboardClear(theClipboard); PasteboardSynchronize(theClipboard); BYTE *pbOutStr = NULL; if (to_utf8(sClip.c_str(), pbOutStr)) { CFDataRef data = CFDataCreate(kCFAllocatorDefault, (UInt8*)pbOutStr, sClip.size() + 1); PasteboardPutItemFlavor(theClipboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), data, 0); } delete[] pbOutStr; return true; #elif defined(__linux__) || defined(__FreeBSD__) bool bSuccess = false; BYTE *pbOutStr = NULL; if (to_utf8(sClip.c_str(), pbOutStr)) bSuccess = SetStringUTF8((const char*)pbOutStr); delete[] pbOutStr; return bSuccess; #elif defined(__native_client__) return false; #else #error CClipboard::SetString -- Unicode not implemented #endif }
//***************************************************************************** bool CUtil::DoesFileExist( //Does a file exist? // //Params: const WCHAR* pszFilepath) //(in) Either full path to file or just the // filename. In the latter case, the // object path is used. // //Returns: //True if it does, false if it doesn't. const { //Check for path separators in file. WSTRING strFullPath; const WCHAR *pszSeek = pszFilepath; while (*pszSeek != '\0' && *pszSeek != SLASH) ++pszSeek; if (*pszSeek == SLASH) //Found a path separator, so treat as a full path. strFullPath = pszFilepath; else //Looks like just a filename. { //Concat full path from object path and filename. strFullPath = this->strPath.c_str(); strFullPath += wszSlash; strFullPath += pszFilepath; } //Open the file to verify its existence. The call below will not leave //the file open. return CFiles::DoesFileExist(strFullPath.c_str()); }
//***************************************************************************** bool CDbMessageText::operator == (const WSTRING &text) //Compare two strings. // //NOTE: This method cannot be const! { return (WCScmp((const WCHAR *)*this, text.c_str()) == 0); }
//***************************************************************************** void CFileDialogWidget::SelectFile() //Selects the file selected in the list box. { const WSTRING wFilename = this->pFileListBoxWidget->GetSelectedItemText(); if (!wFilename.empty()) this->pFilenameTextBox->SetText(wFilename.c_str()); CheckTextBox(); }
//***************************************************************************** vector<WSTRING> CFileDialogWidget::GetSelectedFileNames() const //Returns: a vector of full file names { vector<WSTRING> wFilenames = this->pFileListBoxWidget->GetSelectedItemTexts(); if (wFilenames.empty()) { //No files selected, so use the written text only. wFilenames.push_back(GetSelectedFileName()); return wFilenames; } for (vector<WSTRING>::iterator wFilename = wFilenames.begin(); wFilename != wFilenames.end(); ++wFilename) { WSTRING filename = this->dirpath; filename += wszSlash; filename += *wFilename; //Add extension if it's missing. WSTRING ext; UINT i; for (i=0; i<pExtensionListBoxWidget->GetItemCount(); ++i) { ext = wszPeriod; ext += this->extensions[pExtensionListBoxWidget->GetKeyAtLine(i)]; if (!WCSicmp(filename.c_str() + WCSlen(filename.c_str()) - ext.size(), ext.c_str())) break; } if (i==pExtensionListBoxWidget->GetItemCount()) { //Extension is missing. Add the selected one. ext = wszPeriod; ext += this->extensions[pExtensionListBoxWidget->GetSelectedItem()]; filename += ext.c_str(); } (*wFilename) = filename; } return wFilenames; }
//***************************************************************************** UINT CDrodFileDialogWidget::GetExtensionType(const WSTRING& wFilename) //Determine file type based on file name extension. { UINT ext; for (ext = 0; ext < FileExtension::EXT_COUNT; ++ext) { WSTRING wstrExt = wszPeriod; wstrExt += g_pTheDB->GetMessageText(fileExtension[ext]); if (!WCSicmp(wFilename.c_str() + WCSlen(wFilename.c_str()) - wstrExt.size(), wstrExt.c_str())) { //Recognized file extension. return ext; } } //On older OSes, only 3-character extensions are recognized. //If none of the above matches worked, try matching against shortened extensions. for (ext = 0; ext < FileExtension::EXT_COUNT; ++ext) { WSTRING wstrExt = wszPeriod; wstrExt += g_pTheDB->GetMessageText(fileExtension[ext]); if (wstrExt.length() > 4) //don't retest extensions that were already short enough { wstrExt.resize(4); //.ext if (!WCSicmp(wFilename.c_str() + WCSlen(wFilename.c_str()) - wstrExt.size(), wstrExt.c_str())) { //Recognized file extension. return ext; } } } return FileExtension::EXT_COUNT; //extension not recognized }
//***************************************************************************** void CEntranceSelectDialogWidget::AddEntranceToList(CEntranceData *pEntrance) { const WSTRING descText = pEntrance->GetPositionDescription(); this->pListBoxWidget->AddItem(pEntrance->dwEntranceID, descText.c_str()); }
//***************************************************************************** void CLevelSelectDialogWidget::PopulateLevelList() //Populate list box with all active levels. //List can be toggled between levels in this hold and all levels. { //!! #ifdef AFTERVERSION1_6 const bool bShowAllLevels = DYN_CAST(COptionButtonWidget*, CWidget*, GetWidget(TAG_ALL_LEVELS_OPTIONBOX))->IsChecked(); #else const bool bShowAllLevels = false; #endif this->pLevelListBoxWidget->Clear(); BEGIN_DBREFCOUNT_CHECK; { //Default choice. this->pLevelListBoxWidget->AddItem(0L, g_pTheDB->GetMessageText(MID_DefaultExit)); CDbHold *pHold; CDbLevel *pLevel; if (bShowAllLevels) { //Get all levels in DB. Sort by hold. CDb db; pHold = db.Holds.GetFirst(); while (pHold) { //Allow selecting levels from hold only if player has access rights. if (db.Holds.PlayerCanEditHold(pHold->dwHoldID)) { static const WCHAR wszHoldSep[] = {W_t(' '),W_t(':'),W_t(' '),W_t(0)}; WSTRING wHoldName = (WSTRING)pHold->NameText; wHoldName += wszHoldSep; db.Levels.FilterBy(pHold->dwHoldID); pLevel = db.Levels.GetFirst(); while (pLevel) { ASSERT(pLevel->dwLevelID); WSTRING wText = wHoldName; wText += pLevel->NameText; pLevelListBoxWidget->AddItem(pLevel->dwLevelID, wText.c_str()); delete pLevel; pLevel = db.Levels.GetNext(); } } delete pHold; pHold = db.Holds.GetNext(); } } else { //Get the levels in the current level's hold. if (!this->pSourceLevel) return; CDbHold *pHold = g_pTheDB->Holds.GetByID(this->pSourceLevel->dwHoldID); pLevel = pHold->Levels.GetFirst(); while (pLevel) { ASSERT(pLevel->dwLevelID); pLevelListBoxWidget->AddItem(pLevel->dwLevelID, pLevel->NameText); delete pLevel; pLevel = pHold->Levels.GetNext(); } delete pHold; } } END_DBREFCOUNT_CHECK; }
//***************************************************************************** void CHTMLWidget::StartElement( //Expat callback function: Process XML start tag, and attributes. // //Params: const XML_Char *name, const XML_Char **atts) { //Get tag type (assume no special chars). const HTMLTagType eTagType = ParseTag(name); if (wstrBuffer.length()) Flush(); ++aeTagLevel[eTagType]; //Get id/name attribute { static const WCHAR wszID[] = {We('i'),We('d'),We(0)}; static const WCHAR wszNAME[] = {We('n'),We('a'),We('m'),We('e'),We(0)}; WSTRING tmp = GetAttr(wszID, atts); if (tmp.empty()) tmp = GetAttr(wszNAME, atts); if (!tmp.empty()) mIdmap.insert(std::make_pair(tmp, this->wY)); } switch (eTagType) { case BODY_Tag: { static const WCHAR wszBgcolor[] = {We('b'),We('g'),We('c'),We('o'),We('l'),We('o'),We('r'),We(0)}; WSTRING bgcolor = GetAttr(wszBgcolor, atts); if (bgcolor.size()) this->wstrBGColor = bgcolor; break; } case UL_Tag: case OL_Tag: this->swOLstack.push(this->wOLcounter); this->wOLcounter = (eTagType == OL_Tag ? 1 : 0); this->wMargin += LISTINDENT; NewLine(this->swOLstack.size() == 1); break; case H1_Tag: case H2_Tag: case H3_Tag: NewLine(); break; case TITLE_Tag: wstrTitle = wszEmpty; break; case A_Tag: swstrLink.push(GetAttr(wszHREF, atts)); break; case B_Tag: break; case HR_Tag: case BR_Tag: NewLine(true); break; case IMG_Tag: { static const WCHAR wszSrc[] = {We('s'),We('r'),We('c'),We(0)}; WSTRING imageURL = this->wstrBasePath; imageURL += wszSlash; imageURL += GetAttr(wszSrc, atts); CImageWidget *pImage = new CImageWidget(0, this->wX + this->wMargin, this->wY, imageURL.c_str()); ASSERT(pImage); AddWidget(pImage); this->wY += pImage->GetH(); this->wX = 0; //next thing goes on new line break; } case P_Tag: this->wY += static_cast<UINT>(g_pTheFM->GetFontLineHeight(FONTLIB::F_Text) * 2/3); break; case LI_Tag: { //Use image as bullet in stead ? static const WCHAR wszItem[] = {We('*'),We(' '),We(0)}; NewLine(); if (this->wOLcounter) { WCHAR wszBuf[33]; wstrBuffer = (WSTRING)_itow(this->wOLcounter, wszBuf, 10) + wszPeriod + wszSpace; ++this->wOLcounter; } else wstrBuffer = wszItem; Flush(true); this->bSkipSpace = true; break; } case TABLE_Tag: NewLine(); vwColumns.clear(); //Fall through case TR_Tag: this->wCurrentColumn = 0; break; case TD_Tag: { if (this->wCurrentColumn >= vwColumns.size()) { static const WCHAR wszWidth[] = {We('w'),We('i'),We('d'),We('t'),We('h'),We(0)}; WSTRING wstrWidthAttr = GetAttr(wszWidth, atts); this->wTDWidth = wstrWidthAttr.length() > 0 ? _Wtoi(wstrWidthAttr.c_str()) : 0; vwColumns.push_back(this->wX += 32); } else { this->wX = vwColumns[this->wCurrentColumn]; this->wTDWidth = 0; } ++this->wCurrentColumn; this->bSkipSpace = true; break; } default: break; } }
//***************************************************************************** bool CHTMLWidget::LoadFile( //Load a file and parse it. // //Params: const WCHAR *pwczFileName, //(in) File to load, or NULL to load index. bool bNewLink, //(in) Whether page is new (not from the // forward/back lists). UINT wScrollY) //(in) Pixels to scroll down page initially // (ignored if the filename contains a // valid in-page anchor reference) // //Returns: whether page load was successful. { bool bFullPath = false; if (!pwczFileName) pwczFileName = this->wstrIndexPage.c_str(); //default = index page if (!WCSlen(pwczFileName)) return false; //empty name WSTRING wNewPage = pwczFileName; WSTRING wGoToId; UINT refpos = (UINT)-1; //Very simple path finder for (UINT i = WCSlen(pwczFileName); i--;) { if (pwczFileName[i] == SLASH) { bFullPath = true; this->wstrBasePath = wNewPage.substr(0, i); break; } else if (pwczFileName[i] == '#') { refpos = i; wGoToId = &pwczFileName[i+1]; } } if (refpos != (UINT)-1) wNewPage = refpos ? wNewPage.substr(0, refpos) : this->wstrCurrentPage; if (refpos && !bFullPath) wNewPage = this->wstrBasePath + wszSlash + wNewPage; if (bNewLink) { //Add previous page to back list. Clear forward history. GetScrollOffset(this->nOffsetX, this->nOffsetY); SHTMLPos prev; prev.wstrLink = this->wstrCurrentPage; prev.wY = -this->nOffsetY; if (!this->wstrCurrentPage.empty()) this->swstrBackLink.push(prev); while (!swstrForwardLink.empty()) this->swstrForwardLink.pop(); } //Only load if page requested isn't already being shown. if (WCScmp(wNewPage.c_str(), this->wstrCurrentPage.c_str())) { CStretchyBuffer text; CFiles files; if (!files.ReadFileIntoBuffer(wNewPage.c_str(), text)) return false; this->wstrCurrentPage = wNewPage; this->wstrCurrentId = wGoToId; VERIFY(Parse(text)); //parse should be successful, but return true in any case } //Scroll to id or specified Y-position, if possible if (this->pParent && this->pParent->GetType() == WT_Scrollable) { if (!wGoToId.empty()) { HTMLIDMAP::const_iterator idit = mIdmap.find(wGoToId); if (idit != mIdmap.end()) wScrollY = (*idit).second; } CScrollableWidget *pContainer = DYN_CAST(CScrollableWidget*, CWidget*, this->pParent); pContainer->ScrollAbsolute(0, 0); pContainer->ScrollDownPixels(wScrollY); } return true; }