コード例 #1
0
ファイル: upath.c プロジェクト: sesc4mt/mvcdecoder
static ALLEGRO_PATH *_unix_find_home(void)
{
   char *home_env = getenv("HOME");

   if (!home_env || home_env[0] == '\0') {
      /* since HOME isn't set, we have to ask libc for the info */

      /* get user id */
      uid_t uid = getuid();

      /* grab user information */
      struct passwd *pass = getpwuid(uid);
      if (!pass) {
         al_set_errno(errno);
         return NULL;
      }

      if (pass->pw_dir) {
         /* hey, we got our home directory */
         return al_create_path_for_directory(pass->pw_dir);
      }
      al_set_errno(ENOENT);
      return NULL;
   }
   else {
      return al_create_path_for_directory(home_env);
   }
}
コード例 #2
0
static ALLEGRO_PATH *follow_symlinks(ALLEGRO_PATH *path)
{
   for (;;) {
      const char *path_str = al_path_cstr(path, '/');
      char buf[PATH_MAX];
      int len;

      len = readlink(path_str, buf, sizeof(buf) - 1);
      if (len <= 0)
         break;
      buf[len] = '\0';
      al_destroy_path(path);
      path = al_create_path(buf);
   }

   /* Make absolute path. */
   {
      const char *cwd = al_get_current_directory();
      ALLEGRO_PATH *cwd_path = al_create_path_for_directory(cwd);
      if (al_rebase_path(cwd_path, path))
         al_make_path_canonical(path);
      al_destroy_path(cwd_path);
      al_free((void *) cwd);
   }

   return path;
}
コード例 #3
0
ファイル: path.c プロジェクト: trezker/allua
static int allua_Path_create_for_directory(lua_State * L)
{
   const char *str = luaL_checkstring(L, 1);

   ALLUA_path path = al_create_path_for_directory(str);
   allua_pushPath(L, path, true);

   return 1;
}
コード例 #4
0
ファイル: upath.c プロジェクト: sesc4mt/mvcdecoder
/* _find_executable_file:
 *  Helper function: searches path and current directory for executable.
 *  Returns 1 on succes, 0 on failure.
 */
static ALLEGRO_PATH *_find_executable_file(const char *filename)
{
   char *env;

   /* If filename has an explicit path, search current directory */
   if (strchr(filename, '/')) {
      if (filename[0] == '/') {
         /* Full path; done */
         return al_create_path(filename);
      }
      else {
         struct stat finfo;
         char pathname[1024];
    
         /* Prepend current directory */
         ALLEGRO_PATH *path = al_get_current_directory();
         al_append_path_component(path, filename);

         if ((stat(pathname, &finfo)==0) &&
            (!S_ISDIR (finfo.st_mode))) {
            return path;
         }
      }
   }
   /* If filename has no explicit path, but we do have $PATH, search
    * there
    */
   else if ((env = getenv("PATH"))) {
      struct stat finfo;
      ALLEGRO_USTR *us = al_ustr_new(env);
      int start_pos = 0;
      while (start_pos >= 0) {
         int next_start_pos = al_ustr_find_chr(us, start_pos + 1, ':');
         int end_pos = next_start_pos;
         if (next_start_pos < 0)
            end_pos = al_ustr_size(us);
         ALLEGRO_USTR_INFO info;
         ALLEGRO_USTR *sub = al_ref_ustr(&info, us, start_pos, end_pos);

         ALLEGRO_PATH *path = al_create_path_for_directory(al_cstr(sub));
         al_append_path_component(path, filename);

         if (stat(al_path_cstr(path, '/'), &finfo) == 0 &&
            !S_ISDIR (finfo.st_mode)) {
            return path;
         }
         start_pos = next_start_pos;
      }
   }

   return NULL;
}
コード例 #5
0
ファイル: system.c プロジェクト: ptitSeb/allegro51-pandora
/* al_get_standard_path() does not work before the system driver is
 * initialised.  Before that, we need to call the underlying functions
 * directly.
 */
static ALLEGRO_PATH *early_get_exename_path(void)
{
#if defined(ALLEGRO_WINDOWS)
   return _al_win_get_path(ALLEGRO_EXENAME_PATH);
#elif defined(ALLEGRO_MACOSX)
   return _al_osx_get_path(ALLEGRO_EXENAME_PATH);
#elif defined(ALLEGRO_IPHONE)
   return _al_iphone_get_path(ALLEGRO_EXENAME_PATH);
#elif defined(ALLEGRO_UNIX)
   return _al_unix_get_path(ALLEGRO_EXENAME_PATH);
#elif defined(ALLEGRO_ANDROID)
   return _al_android_get_path(ALLEGRO_EXENAME_PATH);
#elif defined(ALLEGRO_SDL)
   return al_create_path_for_directory(SDL_GetBasePath());
#else
   #error early_get_exename_path not implemented
#endif
}
コード例 #6
0
ファイル: wsystem.c プロジェクト: BorisCarvajal/allegro5
/* _al_win_get_path:
 *  Returns full path to various system and user diretories
 */
ALLEGRO_PATH *_al_win_get_path(int id)
{
    char path[MAX_PATH];
    wchar_t pathw[MAX_PATH];
    ALLEGRO_USTR *pathu;
    uint32_t csidl = 0;
    HRESULT ret = 0;
    ALLEGRO_PATH *cisdl_path = NULL;

    switch (id) {
    case ALLEGRO_TEMP_PATH: {
        /* Check: TMP, TMPDIR, TEMP or TEMPDIR */

        DWORD ret = GetTempPathW(MAX_PATH, pathw);
        if (ret > MAX_PATH) {
            /* should this ever happen, windows is more broken than I ever thought */
            return NULL;
        }
        pathu = al_ustr_new_from_utf16(pathw);
        al_ustr_to_buffer(pathu, path, sizeof path);
        al_ustr_free(pathu);
        return al_create_path_for_directory(path);

    }
    break;

    case ALLEGRO_RESOURCES_PATH: { /* where the program is in */
        HANDLE process = GetCurrentProcess();
        char *ptr;

        GetModuleFileNameExW(process, NULL, pathw, MAX_PATH);
        pathu = al_ustr_new_from_utf16(pathw);
        al_ustr_to_buffer(pathu, path, sizeof path);
        al_ustr_free(pathu);
        ptr = strrchr(path, '\\');
        if (!ptr) { /* shouldn't happen */
            return NULL;
        }

        /* chop off everything including and after the last slash */
        /* should this not chop the slash? */
        *ptr = '\0';

        return al_create_path_for_directory(path);
    }
    break;

    case ALLEGRO_USER_DATA_PATH: /* CSIDL_APPDATA */
    case ALLEGRO_USER_SETTINGS_PATH:
        csidl = CSIDL_APPDATA;
        break;

    case ALLEGRO_USER_HOME_PATH: /* CSIDL_PROFILE */
        csidl = CSIDL_PROFILE;
        break;

    case ALLEGRO_USER_DOCUMENTS_PATH: /* CSIDL_PERSONAL */
        csidl = CSIDL_PERSONAL;
        break;

    case ALLEGRO_EXENAME_PATH: { /* full path to the exe including its name */
        HANDLE process = GetCurrentProcess();

        GetModuleFileNameExW(process, NULL, pathw, MAX_PATH);
        pathu = al_ustr_new_from_utf16(pathw);
        al_ustr_to_buffer(pathu, path, sizeof path);
        al_ustr_free(pathu);

        return al_create_path(path);
    }
    break;

    default:
        return NULL;
    }

    ret = SHGetFolderPathW(NULL, csidl, NULL, SHGFP_TYPE_CURRENT, pathw);
    if (ret != S_OK) {
        return NULL;
    }

    pathu = al_ustr_new_from_utf16(pathw);
    al_ustr_to_buffer(pathu, path, sizeof path);
    al_ustr_free(pathu);

    cisdl_path = al_create_path_for_directory(path);
    if (!cisdl_path)
        return NULL;

    if (csidl == CSIDL_APPDATA) {
        const char *org_name = al_get_org_name();
        const char *app_name = al_get_app_name();

        if (!app_name || !app_name[0]) {
            /* this shouldn't ever happen. */
            al_destroy_path(cisdl_path);
            return NULL;
        }

        if (org_name && org_name[0]) {
            al_append_path_component(cisdl_path, org_name);
        }

        al_append_path_component(cisdl_path, app_name);
    }

    return cisdl_path;
}
コード例 #7
0
ファイル: win_dialog.c プロジェクト: dradtke/battlechess
bool _al_show_native_file_dialog(ALLEGRO_DISPLAY *display,
   ALLEGRO_NATIVE_DIALOG *fd)
{
   OPENFILENAME ofn;
   ALLEGRO_DISPLAY_WIN *win_display;
   int flags = 0;
   bool ret;
   char buf[4096] = "";
   ALLEGRO_USTR *filter_string = NULL;

   win_display = (ALLEGRO_DISPLAY_WIN *)display;

   if (fd->flags & ALLEGRO_FILECHOOSER_FOLDER) {
      return select_folder(win_display, fd);
   }

   /* Selecting a file. */
   memset(&ofn, 0, sizeof(OPENFILENAME));
   ofn.lStructSize = sizeof(OPENFILENAME);
   ofn.hwndOwner = (win_display) ? win_display->window : NULL;

   /* Create filter string. */
   if (fd->fc_patterns) {
      filter_string = create_filter_string(fd->fc_patterns);
      ofn.lpstrFilter = al_cstr(filter_string);
   }
   else {
      /* List all files by default. */
      ofn.lpstrFilter = "All Files\0*.*\0\0";
   }

   ofn.lpstrFile = buf;
   ofn.nMaxFile = sizeof(buf);

   if (fd->fc_initial_path) {
      ofn.lpstrInitialDir =
         al_path_cstr(fd->fc_initial_path, ALLEGRO_NATIVE_PATH_SEP);
   }

   if (fd->title)
      ofn.lpstrTitle = al_cstr(fd->title);

   flags |= OFN_NOCHANGEDIR | OFN_EXPLORER;
   if (fd->flags & ALLEGRO_FILECHOOSER_SAVE) {
      flags |= OFN_OVERWRITEPROMPT;
   }
   else {
      flags |= (fd->flags & ALLEGRO_FILECHOOSER_FILE_MUST_EXIST) ? OFN_FILEMUSTEXIST : 0;
   }
   flags |= (fd->flags & ALLEGRO_FILECHOOSER_MULTIPLE) ? OFN_ALLOWMULTISELECT : 0;
   flags |= (fd->flags & ALLEGRO_FILECHOOSER_SHOW_HIDDEN) ? 0x10000000 : 0; // NOTE: 0x10000000 is FORCESHOWHIDDEN
   ofn.Flags = flags;

   if (flags & OFN_OVERWRITEPROMPT) {
      ret = GetSaveFileName(&ofn);
   }
   else {
      ret = GetOpenFileName(&ofn);
   }

   al_ustr_free(filter_string);

   if (!ret) {
      DWORD err = GetLastError();
      if (err != ERROR_SUCCESS) {
         char buf[1000];
         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, buf, sizeof(buf), NULL);
         ALLEGRO_ERROR("al_show_native_file_dialog failed: %s\n", buf);
      }
      return false;
   }

   if (flags & OFN_ALLOWMULTISELECT) {
      int i;
      /* Count number of file names in buf. */
      fd->fc_path_count = 0;
      i = skip_nul_terminated_string(buf);
      while (1) {
         if (buf[i] == '\0') {
            fd->fc_path_count++;
            if (buf[i+1] == '\0')
               break;
         }
         i++;
      }
   }
   else {
      fd->fc_path_count = 1;
   }

   if (fd->fc_path_count == 1) {
      fd->fc_paths = al_malloc(sizeof(void *));
      fd->fc_paths[0] = al_create_path(buf);
   }
   else {
      int i, p;
      /* If multiple files were selected, the first string in buf is the
       * directory name, followed by each of the file names terminated by NUL.
       */
      fd->fc_paths = al_malloc(fd->fc_path_count * sizeof(void *));
      i = skip_nul_terminated_string(buf);
      for (p = 0; p < (int)fd->fc_path_count; p++) {
         fd->fc_paths[p] = al_create_path_for_directory(buf);
         al_set_path_filename(fd->fc_paths[p], buf+i);
         i += skip_nul_terminated_string(buf+i);
      }
   }

   return true;
}
コード例 #8
0
ファイル: parser.c プロジェクト: dradtke/allegro_tiled
/*
 * Parse a map file into an `ALLEGRO_MAP` struct. By default, relative values of `dir`
 * will be resolved relative to the path of the running executable. To change this,
 * call `al_find_resources_as(RELATIVE_TO_CWD);` first.
 */
ALLEGRO_MAP *al_open_map(const char *dir, const char *filename)
{
	char *cwd = al_get_current_directory();
	if (!cwd) {
		fprintf(stderr, "failed to get cwd; errno = %d", al_get_errno());
		return NULL;
	}

	// `resources` will point to either cwd or the location of the running executable,
	// depending on what was passed in for `rel`.
	ALLEGRO_PATH *resources;
	switch (resources_rel_to) {
		case RELATIVE_TO_EXE:
			resources = al_get_standard_path(ALLEGRO_RESOURCES_PATH);
			break;

		case RELATIVE_TO_CWD:
			resources = al_create_path_for_directory(cwd);
			break;

		default:
			fprintf(stderr, "unexpected value for `resources_rel_to` in al_open_map(): %d\n",
					resources_rel_to);
			al_free(cwd);
			return NULL;
	}

	ALLEGRO_PATH *map_dir = al_create_path_for_directory(dir);

	// Change directory to <cwd>/dir if dir is relative, otherwise dir.
	ALLEGRO_PATH *new_path = (al_join_paths(resources, map_dir) ? resources : map_dir);
	const char *new_path_cstr = al_path_cstr(new_path, ALLEGRO_NATIVE_PATH_SEP);
	if (!al_change_directory(new_path_cstr)) {
		fprintf(stderr, "Error: failed to cd into `%s` in al_open_map().\n",
				new_path_cstr);

		al_destroy_path(resources);
		al_destroy_path(map_dir);
		al_free(cwd);
		return NULL;
	}

	al_destroy_path(resources);
	al_destroy_path(map_dir);

	// Read in the data file
	xmlDoc *doc = xmlReadFile(filename, NULL, 0);
	if (!doc) {
		fprintf(stderr, "Error: failed to parse map data: %s\n", filename);
		al_free(cwd);
		return NULL;
	}

	// Get the root element, <map>
	xmlNode *root = xmlDocGetRootElement(doc);

	// Get some basic info
	ALLEGRO_MAP *map = MALLOC(ALLEGRO_MAP);
	map->width = atoi(get_xml_attribute(root, "width"));
	map->height = atoi(get_xml_attribute(root, "height"));
	map->tile_width = atoi(get_xml_attribute(root, "tilewidth"));
	map->tile_height = atoi(get_xml_attribute(root, "tileheight"));
	map->orientation = g_strdup(get_xml_attribute(root, "orientation"));
	map->tile_layer_count = 0;
	map->object_layer_count = 0;

	// Get the tilesets
	GSList *tilesets = get_children_for_name(root, "tileset");
	map->tilesets = NULL;

	GSList *tileset_item = tilesets;
	while (tileset_item) {
		xmlNode *tileset_node = (xmlNode*)tileset_item->data;
		tileset_item = g_slist_next(tileset_item);

		ALLEGRO_MAP_TILESET *tileset = MALLOC(ALLEGRO_MAP_TILESET);
		tileset->firstgid = atoi(get_xml_attribute(tileset_node, "firstgid"));
		tileset->tilewidth = atoi(get_xml_attribute(tileset_node, "tilewidth"));
		tileset->tileheight = atoi(get_xml_attribute(tileset_node, "tileheight"));
		tileset->name = g_strdup(get_xml_attribute(tileset_node, "name"));

		// Get this tileset's image
		xmlNode *image_node = get_first_child_for_name(tileset_node, "image");
		tileset->width = atoi(get_xml_attribute(image_node, "width"));
		tileset->height = atoi(get_xml_attribute(image_node, "height"));
		tileset->source = g_strdup(get_xml_attribute(image_node, "source"));
		tileset->bitmap = al_load_bitmap(tileset->source);
		if (!tileset->bitmap) {
			fprintf(stderr, "Error: no bitmap available; did you load the image addon?\n");
		}

		// Get this tileset's tiles
		GSList *tiles = get_children_for_name(tileset_node, "tile");
		tileset->tiles = NULL;

		GSList *tile_item = tiles;
		while (tile_item) {
			xmlNode *tile_node = (xmlNode*)tile_item->data;
			tile_item = g_slist_next(tile_item);

			ALLEGRO_MAP_TILE *tile = MALLOC(ALLEGRO_MAP_TILE);
			tile->id = tileset->firstgid + atoi(get_xml_attribute(tile_node, "id"));
			tile->tileset = tileset;
			tile->bitmap = NULL;

			// Get this tile's properties
			tile->properties = parse_properties(tile_node);

			// TODO: add a destructor
			tileset->tiles = g_slist_prepend(tileset->tiles, tile);
		}

		g_slist_free(tiles);
		//tileset->tiles = g_slist_reverse(tileset->tiles);

		// TODO: add a destructor
		map->tilesets = g_slist_prepend(map->tilesets, tileset);
	}

	g_slist_free(tilesets);
	//map->tilesets = g_slist_reverse(map->tilesets);

	// Create the map's master list of tiles
	cache_tile_list(map);

	// Get the layers
	GSList *layers = get_children_for_either_name(root, "layer", "objectgroup");
	map->layers = NULL;

	GSList *layer_item = layers;
	while (layer_item) {
		xmlNode *layer_node = (xmlNode*)layer_item->data;
		layer_item = g_slist_next(layer_item);

		ALLEGRO_MAP_LAYER *layer = MALLOC(ALLEGRO_MAP_LAYER);
		layer->name = g_strdup(get_xml_attribute(layer_node, "name"));
		layer->properties = parse_properties(layer_node);

		char *layer_visible = get_xml_attribute(layer_node, "visible");
		layer->visible = (layer_visible != NULL ? atoi(layer_visible) : 1);

		char *layer_opacity = get_xml_attribute(layer_node, "opacity");
		layer->opacity = (layer_opacity != NULL ? atof(layer_opacity) : 1.0);

		if (!strcmp((const char*)layer_node->name, "layer")) {
			layer->type = TILE_LAYER;
			layer->width = atoi(get_xml_attribute(layer_node, "width"));
			layer->height = atoi(get_xml_attribute(layer_node, "height"));
			decode_layer_data(get_first_child_for_name(layer_node, "data"), layer);

			// Create any missing tile objects
			unsigned i, j;
			for (i = 0; i < layer->height; i++) {
				for (j = 0; j < layer->width; j++) {
					char id = al_get_single_tile_id(layer, j, i);

					if (id == 0) {
						continue;
					}

					ALLEGRO_MAP_TILE *tile = al_get_tile_for_id(map, id);
					if (!tile) {
						// wasn't defined in the map file, presumably because it had no properties
						tile = MALLOC(ALLEGRO_MAP_TILE);
						tile->id = id;
						tile->properties = g_hash_table_new(NULL, NULL);
						tile->tileset = NULL;
						tile->bitmap = NULL;

						// locate its tilemap
						GSList *tilesets = map->tilesets;
						ALLEGRO_MAP_TILESET *tileset_ref;
						while (tilesets) {
							ALLEGRO_MAP_TILESET *tileset = (ALLEGRO_MAP_TILESET*)tilesets->data;
							tilesets = g_slist_next(tilesets);
							if (tileset->firstgid <= id) {
								if (!tile->tileset || tileset->firstgid > tile->tileset->firstgid) {
									tileset_ref = tileset;
								}
							}

						}

						tile->tileset = tileset_ref;
						tileset_ref->tiles = g_slist_prepend(tileset_ref->tiles, tile);
						g_hash_table_insert(map->tiles, GINT_TO_POINTER(tile->id), tile);
					}

					// create this tile's bitmap if it hasn't been yet
					if (!tile->bitmap) {
						ALLEGRO_MAP_TILESET *tileset = tile->tileset;
						int id = tile->id - tileset->firstgid;
						int width = tileset->width / tileset->tilewidth;
						int x = (id % width) * tileset->tilewidth;
						int y = (id / width) * tileset->tileheight;
						if (tileset->bitmap) {
							tile->bitmap = al_create_sub_bitmap(
									tileset->bitmap,
									x, y,
									tileset->tilewidth,
									tileset->tileheight);
						}
					}
				}
			}
			map->tile_layer_count++;
			map->tile_layers = g_slist_prepend(map->tile_layers, layer);
		} else if (!strcmp((const char*)layer_node->name, "objectgroup")) {
			layer->type = OBJECT_LAYER;
			layer->objects = NULL;
			layer->object_count = 0;
			// TODO: color?
			GSList *objects = get_children_for_name(layer_node, "object");
			GSList *object_item = objects;
			while (object_item) {
				xmlNode *object_node = (xmlNode*)object_item->data;
				object_item = g_slist_next(object_item);

				ALLEGRO_MAP_OBJECT *object = MALLOC(ALLEGRO_MAP_OBJECT);
				object->layer = layer;
				object->name = g_strdup(get_xml_attribute(object_node, "name"));
				object->type = g_strdup(get_xml_attribute(object_node, "type"));
				object->x = atoi(get_xml_attribute(object_node, "x"));
				object->y = atoi(get_xml_attribute(object_node, "y"));
				object->bitmap = NULL;

				char *object_width = get_xml_attribute(object_node, "width");
				object->width = (object_width ? atoi(object_width) : 0);

				char *object_height = get_xml_attribute(object_node, "height");
				object->height = (object_height ? atoi(object_height) : 0);

				char *gid = get_xml_attribute(object_node, "gid");
				object->gid = (gid ? atoi(gid) : 0);

				char *object_visible = get_xml_attribute(object_node, "visible");
				object->visible = (object_visible ? atoi(object_visible) : 1);

				// Get the object's properties
				object->properties = parse_properties(object_node);
				layer->objects = g_slist_prepend(layer->objects, object);
				layer->object_count++;
			}
			map->object_layer_count++;
			map->object_layers = g_slist_prepend(map->object_layers, layer);
		} else {
			fprintf(stderr, "Error: found invalid layer node \"%s\"\n", layer_node->name);
			continue;
		}

		map->layers = g_slist_prepend(map->layers, layer);
	}

	g_slist_free(layers);

	// If any objects have a tile gid, cache their image
	layer_item = map->layers;
	while (layer_item) {
		ALLEGRO_MAP_LAYER *layer = (ALLEGRO_MAP_LAYER*)layer_item->data;
		layer_item = g_slist_next(layer_item);
		if (layer->type != OBJECT_LAYER) {
			continue;
		}

		GSList *objects = layer->objects;
		while (objects) {
			ALLEGRO_MAP_OBJECT *object = (ALLEGRO_MAP_OBJECT*)objects->data;
			objects = g_slist_next(objects);
			if (!object->gid) {
				continue;
			}

			object->bitmap = al_get_tile_for_id(map, object->gid)->bitmap;
			object->width = map->tile_width;
			object->height = map->tile_height;
		}
	}

	xmlFreeDoc(doc);
	al_change_directory(cwd);
	al_free(cwd);

	return map;
}
コード例 #9
0
ALLEGRO_PATH *_al_unix_get_path(int id)
{
   switch (id) {
      case ALLEGRO_TEMP_PATH: {
         /* Check: TMP, TMPDIR, TEMP or TEMPDIR */
         char *envs[] = { "TMP", "TMPDIR", "TEMP", "TEMPDIR", NULL};
         uint32_t i = 0;
         for (; envs[i] != NULL; ++i) {
            char *tmp = getenv(envs[i]);
            if (tmp) {
               return al_create_path_for_directory(tmp);
            }
         }

         /* next try: /tmp /var/tmp /usr/tmp */
         char *paths[] = { "/tmp/", "/var/tmp/", "/usr/tmp/", NULL };
         for (i=0; paths[i] != NULL; ++i) {
            ALLEGRO_FS_ENTRY *fse = al_create_fs_entry(paths[i]);
            bool found = (al_get_fs_entry_mode(fse) & ALLEGRO_FILEMODE_ISDIR) != 0;
            al_destroy_fs_entry(fse);
            if (found) {
               return al_create_path_for_directory(paths[i]);
            }
         }

         /* Give up? */
         return NULL;
      } break;

      case ALLEGRO_RESOURCES_PATH: {
         ALLEGRO_PATH *exe = get_executable_name();
         exe = follow_symlinks(exe);
         al_set_path_filename(exe, NULL);
         return exe;

      } break;

      case ALLEGRO_USER_DATA_PATH:
      case ALLEGRO_USER_SETTINGS_PATH: {
         ALLEGRO_PATH *local_path = NULL;
         const char *org_name = al_get_org_name();
         const char *app_name = al_get_app_name();
         
         /* to avoid writing directly into the user's directory, require at least an app name */
         if (!app_name)
            return NULL;
         
         /* find the appropriate path from the xdg environment variables, if possible */
         if (id == ALLEGRO_USER_DATA_PATH) {
            const char *xdg_data_home = getenv("XDG_DATA_HOME");
            local_path = al_create_path_for_directory(xdg_data_home ? xdg_data_home : ".local/share");
         }
         else {
            const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
            local_path = al_create_path_for_directory(xdg_config_home ? xdg_config_home : ".config");
         }
         
         if (!local_path) 
            return NULL;
         
         /* if the path is relative, prepend the user's home directory */
         if (al_path_cstr(local_path, '/')[0] != '/') {
            ALLEGRO_PATH *home_path = _unix_find_home();
            if (!home_path)
               return NULL;
            
            al_rebase_path(home_path, local_path);
            al_destroy_path(home_path);
         }

         /* only add org name if not blank */
         if (org_name && org_name[0]) {              
            al_append_path_component(local_path, al_get_org_name());
         }
         
         al_append_path_component(local_path, al_get_app_name());

        return local_path;
      } break;

      case ALLEGRO_USER_HOME_PATH:
         return _unix_find_home();
         
      case ALLEGRO_USER_DOCUMENTS_PATH: {
         ALLEGRO_PATH *local_path = _get_xdg_path("DOCUMENTS");
         return local_path ? local_path : _unix_find_home();
      } break;

      case ALLEGRO_EXENAME_PATH:
         return get_executable_name();
         break;

      default:
         return NULL;
   }

   return NULL;
}
コード例 #10
0
/* get_xdg_path - locate an XDG user dir
 */
static ALLEGRO_PATH *_get_xdg_path(const char *location)
{
   ALLEGRO_PATH *location_path = NULL;
   ALLEGRO_PATH *xdg_config_path = NULL;
   ALLEGRO_FILE *xdg_config_file = NULL;   
   const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
   int fd;

   if (xdg_config_home) {
      /* use $XDG_CONFIG_HOME since it exists */
      xdg_config_path = al_create_path_for_directory(xdg_config_home);
   }
   else {
      /* the default XDG location is ~/.config */
      xdg_config_path = al_get_standard_path(ALLEGRO_USER_HOME_PATH);
      if (!xdg_config_path) return NULL;      
      al_append_path_component(xdg_config_path, ".config");
   }   
   
   al_set_path_filename(xdg_config_path, "user-dirs.dirs");
   fd = open(al_path_cstr(xdg_config_path, '/'), O_RDONLY);
   if (fd != -1) {
     xdg_config_file = al_fopen_fd(fd, "r");
   }
   al_destroy_path(xdg_config_path);
   
   if (!xdg_config_file) return NULL;
      
   while (!al_feof(xdg_config_file)) {
      char line[XDG_MAX_PATH_LEN];      /* one line of the config file */
      const char *p = line;             /* where we're at in the line */
      char component[XDG_MAX_PATH_LEN]; /* the path component being parsed */      
      int i = 0;                        /* how long the current component is */

      al_fgets(xdg_config_file, line, XDG_MAX_PATH_LEN);
      
      /* skip leading white space */
      while (*p == ' ' || *p == '\t') p++;
   
      /* skip the line if it does not begin with XDG_location_DIR */            
      if (strncmp(p, "XDG_", 4)) continue;
      p += 4;
      
      if (strncmp(p, location, strlen(location))) continue;
      p += strlen(location);
      
      if (strncmp(p, "_DIR", 4)) continue;
      p += 4;
      
      /* skip past the =", allowing for white space */
      while (*p == ' ' || *p == '\t') p++;      
      if (*p++ != '=') continue;
      while (*p == ' ' || *p == '\t') p++;
      if (*p++ != '"') continue;
      
      /* We've found the right line. Now parse it, basically assuming
         that it is in a sane format. 
       */
      if (!strncmp(p, "$HOME", 5)) {
         /* $HOME is the only environment variable that the path is 
            allowed to use, and it must be first, by specification. */
         location_path = al_get_standard_path(ALLEGRO_USER_HOME_PATH);
         p += 5;
      }
      else {
         location_path = al_create_path("/");
      }
      
      while (*p) {
         if (*p == '"' || *p == '/') {
            /* add the component (if non-empty) to the path */
            if (i > 0) {
               component[i] = 0;
               al_append_path_component(location_path, component);
               i = 0;
            }
            if (*p == '"') break;
         }
         else {
            if (*p == '\\') {
               /* treat any escaped character as a literal */
               p++;
               if (!*p) break;
            }            
            component[i++] = *p;
         }
         
         p++;
      }
      
      /* Finished parsing the path. */
      break;
   }
   
   al_fclose(xdg_config_file);
   
   return location_path;
}