void FontManager::_AddSystemPaths() { BPath path; if (find_directory(B_BEOS_FONTS_DIRECTORY, &path, true) == B_OK) _AddPath(path.Path()); // We don't scan these in test mode to help shave off some startup time #if !TEST_MODE if (find_directory(B_COMMON_FONTS_DIRECTORY, &path, true) == B_OK) _AddPath(path.Path()); #endif }
status_t FontManager::_AddPath(const char* path) { BEntry entry; status_t status = entry.SetTo(path); if (status != B_OK) return status; return _AddPath(entry); }
void FontManager::AttachUser(uid_t userID) { BAutolock locker(this); #if !TEST_MODE // TODO: actually, find_directory() cannot know which user ID we want here // TODO: avoids user fonts in safe mode BPath path; if (find_directory(B_USER_FONTS_DIRECTORY, &path, true) != B_OK) return; _AddPath(path.Path()); #endif }
/*! \brief Scan a folder for all valid fonts \param directoryPath Path of the folder to scan. */ status_t FontManager::_ScanFontDirectory(font_directory& fontDirectory) { // This bad boy does all the real work. It loads each entry in the // directory. If a valid font file, it adds both the family and the style. BDirectory directory; status_t status = directory.SetTo(&fontDirectory.directory); if (status != B_OK) return status; BEntry entry; while (directory.GetNextEntry(&entry) == B_OK) { if (entry.IsDirectory()) { // scan this directory recursively font_directory* newDirectory; if (_AddPath(entry, &newDirectory) == B_OK && newDirectory != NULL) _ScanFontDirectory(*newDirectory); continue; } // TODO: Commenting this out makes my "Unicode glyph lookup" // work with our default fonts. The real fix is to select the // Unicode char map (if supported), and/or adjust the // utf8 -> glyph-index mapping everywhere to handle other // char maps. We could also ignore fonts that don't support // the Unicode lookup as a temporary "solution". #if 0 FT_CharMap charmap = _GetSupportedCharmap(face); if (!charmap) { FT_Done_Face(face); continue; } face->charmap = charmap; #endif _AddFont(fontDirectory, entry); // takes over ownership of the FT_Face object } fontDirectory.revision = 1; return B_OK; }
/*! \brief Creates all unknown font_directories of the specified path - but only if one of its parent directories is already known. This method is used to create the font_directories for font_mappings. It recursively walks upwards in the directory hierarchy until it finds a known font_directory (or hits the root directory, in which case it bails out). */ status_t FontManager::_CreateDirectories(const char* path) { FTRACE(("_CreateDirectories(path = %s)\n", path)); if (!strcmp(path, "/")) { // we walked our way up to the root return B_ENTRY_NOT_FOUND; } BEntry entry; status_t status = entry.SetTo(path); if (status != B_OK) return status; node_ref nodeRef; status = entry.GetNodeRef(&nodeRef); if (status != B_OK) return status; // check if we are already know this directory font_directory* directory = _FindDirectory(nodeRef); if (directory != NULL) return B_OK; // We don't know this one yet - keep walking the path upwards // and try to find a match. BPath parent(path); status = parent.GetParent(&parent); if (status != B_OK) return status; status = _CreateDirectories(parent.Path()); if (status != B_OK) return status; // We have our match, create sub directory return _AddPath(path); }
status_t device_node::_GetNextDriverPath(void*& cookie, KPath& _path) { Stack<KPath*>* stack = NULL; if (cookie == NULL) { // find all paths and add them stack = new(std::nothrow) Stack<KPath*>(); if (stack == NULL) return B_NO_MEMORY; StackDeleter<KPath*> stackDeleter(stack); bool generic = false; uint16 type = 0; uint16 subType = 0; uint16 interface = 0; if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK || get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) != B_OK) generic = true; get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false); // TODO: maybe make this extendible via settings file? switch (type) { case PCI_mass_storage: switch (subType) { case PCI_scsi: _AddPath(*stack, "busses", "scsi"); _AddPath(*stack, "busses", "virtio"); break; case PCI_ide: _AddPath(*stack, "busses", "ata"); _AddPath(*stack, "busses", "ide"); break; case PCI_sata: // TODO: check for ahci interface _AddPath(*stack, "busses", "scsi"); _AddPath(*stack, "busses", "ata"); _AddPath(*stack, "busses", "ide"); break; default: _AddPath(*stack, "busses"); break; } break; case PCI_serial_bus: switch (subType) { case PCI_firewire: _AddPath(*stack, "busses", "firewire"); break; case PCI_usb: _AddPath(*stack, "busses", "usb"); break; default: _AddPath(*stack, "busses"); break; } break; case PCI_network: _AddPath(*stack, "drivers", "net"); _AddPath(*stack, "busses", "virtio"); break; case PCI_display: _AddPath(*stack, "drivers", "graphics"); break; case PCI_multimedia: switch (subType) { case PCI_audio: case PCI_hd_audio: _AddPath(*stack, "drivers", "audio"); break; case PCI_video: _AddPath(*stack, "drivers", "video"); break; default: _AddPath(*stack, "drivers"); break; } break; default: if (sRootNode == this) { _AddPath(*stack, "busses/pci"); _AddPath(*stack, "bus_managers"); } else if (!generic) { _AddPath(*stack, "busses", "virtio"); _AddPath(*stack, "drivers"); } else { // For generic drivers, we only allow busses when the // request is more specified if (sGenericContextPath != NULL && (!strcmp(sGenericContextPath, "disk") || !strcmp(sGenericContextPath, "ports") || !strcmp(sGenericContextPath, "bus"))) { _AddPath(*stack, "busses"); } _AddPath(*stack, "drivers", sGenericContextPath); _AddPath(*stack, "busses/scsi"); _AddPath(*stack, "busses/random"); } break; } stackDeleter.Detach(); cookie = (void*)stack; } else stack = static_cast<Stack<KPath*>*>(cookie); KPath* path; if (stack->Pop(&path)) { _path.Adopt(*path); delete path; return B_OK; } delete stack; return B_ENTRY_NOT_FOUND; }
void FontManager::MessageReceived(BMessage* message) { switch (message->what) { case B_NODE_MONITOR: { // TODO: support removing fonts! int32 opcode; if (message->FindInt32("opcode", &opcode) != B_OK) return; switch (opcode) { case B_ENTRY_CREATED: { const char* name; node_ref nodeRef; if (message->FindInt32("device", &nodeRef.device) != B_OK || message->FindInt64("directory", &nodeRef.node) != B_OK || message->FindString("name", &name) != B_OK) break; // TODO: make this better (possible under Haiku) snooze(100000); // let the font be written completely before trying to open it BEntry entry; if (set_entry(nodeRef, name, entry) != B_OK) break; if (entry.IsDirectory()) { // a new directory to watch for us _AddPath(entry); } else { // a new font font_directory* directory = _FindDirectory(nodeRef); if (directory == NULL) { // unknown directory? how come? break; } _AddFont(*directory, entry); } break; } case B_ENTRY_MOVED: { // has the entry been moved into a monitored directory or has // it been removed from one? const char* name; node_ref nodeRef; uint64 fromNode; uint64 node; if (message->FindInt32("device", &nodeRef.device) != B_OK || message->FindInt64("to directory", &nodeRef.node) != B_OK || message->FindInt64("from directory", (int64 *)&fromNode) != B_OK || message->FindInt64("node", (int64 *)&node) != B_OK || message->FindString("name", &name) != B_OK) break; font_directory* directory = _FindDirectory(nodeRef); BEntry entry; if (set_entry(nodeRef, name, entry) != B_OK) break; if (directory != NULL) { // something has been added to our watched font directories // test, if the source directory is one of ours as well nodeRef.node = fromNode; font_directory* fromDirectory = _FindDirectory(nodeRef); if (entry.IsDirectory()) { if (fromDirectory == NULL) { // there is a new directory to watch for us _AddPath(entry); FTRACE("new directory moved in"); } else { // A directory from our watched directories has // been renamed or moved within the watched // directories - we only need to update the // path names of the styles in that directory nodeRef.node = node; directory = _FindDirectory(nodeRef); if (directory != NULL) { for (int32 i = 0; i < directory->styles.CountItems(); i++) { FontStyle* style = directory->styles.ItemAt(i); style->UpdatePath(directory->directory); } } FTRACE("directory renamed"); } } else { if (fromDirectory != NULL) { // find style in source and move it to the target nodeRef.node = node; FontStyle* style = fromDirectory->FindStyle(nodeRef); if (style != NULL) { fromDirectory->styles.RemoveItem(style, false); directory->styles.AddItem(style); style->UpdatePath(directory->directory); } FTRACE(("font moved")); } else { FTRACE(("font added: %s\n", name)); _AddFont(*directory, entry); } } } else { // and entry has been removed from our font directories if (entry.IsDirectory()) { if (entry.GetNodeRef(&nodeRef) == B_OK && (directory = _FindDirectory(nodeRef)) != NULL) _RemoveDirectory(directory); } else { // remove font style from directory _RemoveStyle(nodeRef.device, fromNode, node); } } break; } case B_ENTRY_REMOVED: { node_ref nodeRef; uint64 directoryNode; if (message->FindInt32("device", &nodeRef.device) != B_OK || message->FindInt64("directory", (int64 *)&directoryNode) != B_OK || message->FindInt64("node", &nodeRef.node) != B_OK) break; font_directory* directory = _FindDirectory(nodeRef); if (directory != NULL) { // the directory has been removed, so we remove it as well _RemoveDirectory(directory); } else { // remove font style from directory _RemoveStyle(nodeRef.device, directoryNode, nodeRef.node); } break; } } break; } } }