Moved moo_app_get_data_dirs and friends into mooutils
parent
e76e7a159f
commit
dadee80e58
|
@ -1,5 +1,5 @@
|
|||
AUTOMAKE_OPTIONS = dist-bzip2
|
||||
EXTRA_DIST = mingw-configure cygwin-configure
|
||||
EXTRA_DIST = autogen.sh mingw-configure cygwin-configure
|
||||
|
||||
DIST_SUBDIRS = m4
|
||||
|
||||
|
|
|
@ -411,6 +411,8 @@ moo_app_constructor (GType type,
|
|||
object = moo_app_parent_class->constructor (type, n_params, params);
|
||||
app = MOO_APP (object);
|
||||
|
||||
g_set_prgname (app->priv->info->short_name);
|
||||
|
||||
if (!app->priv->info->full_name)
|
||||
app->priv->info->full_name = g_strdup (app->priv->info->short_name);
|
||||
|
||||
|
@ -593,120 +595,6 @@ moo_app_set_exit_code (MooApp *app,
|
|||
}
|
||||
|
||||
|
||||
char *
|
||||
moo_app_get_data_dir (MooApp *app,
|
||||
MooAppDataType type)
|
||||
{
|
||||
g_return_val_if_fail (MOO_IS_APP (app), NULL);
|
||||
|
||||
#ifdef __WIN32__
|
||||
g_return_val_if_fail (app->priv->argv && app->priv->argv[0], g_strdup ("."));
|
||||
return g_path_get_dirname (app->priv->argv[0]);
|
||||
#else
|
||||
switch (type)
|
||||
{
|
||||
case MOO_APP_DATA_SHARE:
|
||||
return g_strdup (MOO_DATA_DIR);
|
||||
case MOO_APP_DATA_LIB:
|
||||
return g_strdup (MOO_LIB_DIR);
|
||||
}
|
||||
|
||||
g_return_val_if_reached (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
moo_app_get_user_data_dir (MooApp *app,
|
||||
G_GNUC_UNUSED MooAppDataType type)
|
||||
{
|
||||
G_GNUC_UNUSED char *basename;
|
||||
char *dir;
|
||||
|
||||
#ifdef __WIN32__
|
||||
dir = g_build_filename (g_get_home_dir (), app->priv->info->short_name, NULL);
|
||||
#else
|
||||
basename = g_strdup_printf (".%s", app->priv->info->short_name);
|
||||
dir = g_build_filename (g_get_home_dir (), basename, NULL);
|
||||
g_free (basename);
|
||||
#endif
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
char **
|
||||
moo_app_get_data_dirs (MooApp *app,
|
||||
MooAppDataType type,
|
||||
guint *n_dirs)
|
||||
{
|
||||
const char *env;
|
||||
GPtrArray *dirs;
|
||||
|
||||
g_return_val_if_fail (MOO_IS_APP (app), NULL);
|
||||
|
||||
dirs = g_ptr_array_sized_new (3);
|
||||
env = g_getenv ("MOO_APP_DIRS");
|
||||
|
||||
if (env && *env)
|
||||
{
|
||||
char **env_dirs, **p;
|
||||
|
||||
#ifdef __WIN32__
|
||||
env_dirs = g_strsplit (env, ";", 0);
|
||||
p = moo_filenames_from_locale (env_dirs);
|
||||
g_strfreev (env_dirs);
|
||||
env_dirs = p;
|
||||
#else
|
||||
env_dirs = g_strsplit (env, ":", 0);
|
||||
#endif
|
||||
|
||||
for (p = env_dirs; p && *p; ++p)
|
||||
if (**p)
|
||||
g_ptr_array_add (dirs, *p);
|
||||
else
|
||||
g_free (*p);
|
||||
|
||||
g_free (env_dirs);
|
||||
}
|
||||
|
||||
g_ptr_array_add (dirs, moo_app_get_data_dir (app, type));
|
||||
g_ptr_array_add (dirs, moo_app_get_user_data_dir (app, type));
|
||||
g_ptr_array_add (dirs, NULL);
|
||||
|
||||
if (n_dirs)
|
||||
*n_dirs = dirs->len - 1;
|
||||
|
||||
return (char**) g_ptr_array_free (dirs, FALSE);
|
||||
}
|
||||
|
||||
|
||||
char **
|
||||
moo_app_get_data_subdirs (MooApp *app,
|
||||
const char *subdir,
|
||||
MooAppDataType type,
|
||||
guint *n_dirs_p)
|
||||
{
|
||||
char **data_dirs, **dirs;
|
||||
guint n_dirs, i;
|
||||
|
||||
g_return_val_if_fail (subdir != NULL, NULL);
|
||||
|
||||
data_dirs = moo_app_get_data_dirs (app, type, &n_dirs);
|
||||
g_return_val_if_fail (data_dirs != NULL, NULL);
|
||||
|
||||
if (n_dirs_p)
|
||||
*n_dirs_p = n_dirs;
|
||||
|
||||
dirs = g_new0 (char*, n_dirs + 1);
|
||||
|
||||
for (i = 0; i < n_dirs; ++i)
|
||||
dirs[i] = g_build_filename (data_dirs[i], subdir, NULL);
|
||||
|
||||
return dirs;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
moo_app_get_input_pipe_name (G_GNUC_UNUSED MooApp *app)
|
||||
{
|
||||
|
@ -876,12 +764,12 @@ moo_app_get_context (MooWindow *window)
|
|||
}
|
||||
|
||||
static void
|
||||
moo_app_load_user_actions (MooApp *app)
|
||||
moo_app_load_user_actions (void)
|
||||
{
|
||||
char **dirs;
|
||||
guint n_dirs, i;
|
||||
|
||||
dirs = moo_app_get_data_dirs (app, MOO_APP_DATA_SHARE, &n_dirs);
|
||||
dirs = moo_get_data_dirs (MOO_DATA_SHARE, &n_dirs);
|
||||
g_return_if_fail (dirs != NULL);
|
||||
|
||||
for (i = 0; i < n_dirs; i++)
|
||||
|
@ -913,15 +801,15 @@ moo_app_init_editor (MooApp *app)
|
|||
|
||||
lang_mgr = moo_editor_get_lang_mgr (app->priv->editor);
|
||||
|
||||
dirs = moo_app_get_data_subdirs (app, MOO_LANG_DIR_BASENAME,
|
||||
MOO_APP_DATA_SHARE, &n_dirs);
|
||||
dirs = moo_get_data_subdirs (MOO_LANG_DIR_BASENAME,
|
||||
MOO_DATA_SHARE, &n_dirs);
|
||||
for (i = 0; i < n_dirs; ++i)
|
||||
moo_lang_mgr_add_dir (lang_mgr, dirs[i]);
|
||||
moo_lang_mgr_read_dirs (lang_mgr);
|
||||
g_strfreev (dirs);
|
||||
|
||||
dirs = moo_app_get_data_subdirs (app, MOO_PLUGIN_DIR_BASENAME,
|
||||
MOO_APP_DATA_LIB, &n_dirs);
|
||||
dirs = moo_get_data_subdirs (MOO_PLUGIN_DIR_BASENAME,
|
||||
MOO_DATA_LIB, &n_dirs);
|
||||
moo_set_plugin_dirs (dirs);
|
||||
moo_plugin_init_builtin ();
|
||||
moo_plugin_read_dirs ();
|
||||
|
@ -938,7 +826,7 @@ moo_app_init_ui (MooApp *app)
|
|||
int i;
|
||||
|
||||
xml = moo_app_get_ui_xml (app);
|
||||
dirs = moo_app_get_data_dirs (app, MOO_APP_DATA_SHARE, &n_dirs);
|
||||
dirs = moo_get_data_dirs (MOO_DATA_SHARE, &n_dirs);
|
||||
|
||||
for (i = n_dirs - 1; i >= 0; --i)
|
||||
{
|
||||
|
@ -1052,7 +940,7 @@ moo_app_init_real (MooApp *app)
|
|||
}
|
||||
#endif /* __WIN32__ && MOO_BUILD_TERM */
|
||||
|
||||
moo_app_load_user_actions (app);
|
||||
moo_app_load_user_actions ();
|
||||
|
||||
start_io (app);
|
||||
|
||||
|
@ -1698,26 +1586,6 @@ moo_app_tempnam (MooApp *app)
|
|||
}
|
||||
|
||||
|
||||
GType
|
||||
moo_app_data_type_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (!type)
|
||||
{
|
||||
static const GEnumValue values[] = {
|
||||
{ MOO_APP_DATA_SHARE, (char*) "MOO_APP_DATA_SHARE", (char*) "share" },
|
||||
{ MOO_APP_DATA_LIB, (char*) "MOO_APP_DATA_LIB", (char*) "lib" },
|
||||
{ 0, NULL, NULL },
|
||||
};
|
||||
|
||||
type = g_enum_register_static ("MooAppDataType", values);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
static MSContext *
|
||||
moo_app_get_context_real (G_GNUC_UNUSED MooApp *app,
|
||||
MooWindow *window)
|
||||
|
|
|
@ -22,7 +22,6 @@ G_BEGIN_DECLS
|
|||
|
||||
|
||||
#define MOO_TYPE_APP_INFO (moo_app_info_get_type ())
|
||||
#define MOO_TYPE_APP_DATA_TYPE (moo_app_data_type_get_type ())
|
||||
|
||||
#define MOO_TYPE_APP (moo_app_get_type ())
|
||||
#define MOO_APP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_APP, MooApp))
|
||||
|
@ -37,11 +36,6 @@ typedef struct _MooAppInfo MooAppInfo;
|
|||
typedef struct _MooAppPrivate MooAppPrivate;
|
||||
typedef struct _MooAppClass MooAppClass;
|
||||
|
||||
typedef enum {
|
||||
MOO_APP_DATA_SHARE,
|
||||
MOO_APP_DATA_LIB
|
||||
} MooAppDataType;
|
||||
|
||||
struct _MooAppInfo
|
||||
{
|
||||
char *short_name;
|
||||
|
@ -50,7 +44,6 @@ struct _MooAppInfo
|
|||
char *version;
|
||||
char *website;
|
||||
char *website_label;
|
||||
|
||||
char *rc_file;
|
||||
};
|
||||
|
||||
|
@ -83,7 +76,6 @@ struct _MooAppClass
|
|||
|
||||
GType moo_app_get_type (void) G_GNUC_CONST;
|
||||
GType moo_app_info_get_type (void) G_GNUC_CONST;
|
||||
GType moo_app_data_type_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MooApp *moo_app_get_instance (void);
|
||||
|
||||
|
@ -100,18 +92,6 @@ const char *moo_app_get_rc_file_name (MooApp *app);
|
|||
const char *moo_app_get_input_pipe_name (MooApp *app);
|
||||
const char *moo_app_get_output_pipe_name (MooApp *app);
|
||||
|
||||
char *moo_app_get_data_dir (MooApp *app,
|
||||
MooAppDataType type);
|
||||
char *moo_app_get_user_data_dir (MooApp *app,
|
||||
MooAppDataType type);
|
||||
char **moo_app_get_data_dirs (MooApp *app,
|
||||
MooAppDataType type,
|
||||
guint *n_dirs);
|
||||
char **moo_app_get_data_subdirs (MooApp *app,
|
||||
const char *subdir,
|
||||
MooAppDataType type,
|
||||
guint *n_dirs);
|
||||
|
||||
MooEditor *moo_app_get_editor (MooApp *app);
|
||||
|
||||
void moo_app_prefs_dialog (GtkWidget *parent);
|
||||
|
|
|
@ -25,16 +25,6 @@
|
|||
;; )
|
||||
;; )
|
||||
|
||||
(define-enum DataType
|
||||
(in-module "Moo")
|
||||
(c-name "MooAppDataType")
|
||||
(gtype-id "MOO_TYPE_APP_DATA_TYPE")
|
||||
(values
|
||||
'("share" "MOO_APP_DATA_SHARE")
|
||||
'("lib" "MOO_APP_DATA_LIB")
|
||||
)
|
||||
)
|
||||
|
||||
;; From mooapp.h
|
||||
|
||||
(define-function get_instance
|
||||
|
@ -145,42 +135,3 @@
|
|||
'("int" "len")
|
||||
)
|
||||
)
|
||||
|
||||
(define-method get_data_dir
|
||||
(of-object "MooApp")
|
||||
(c-name "moo_app_get_data_dir")
|
||||
(return-type "char*")
|
||||
(parameters
|
||||
'("MooAppDataType" "type")
|
||||
)
|
||||
)
|
||||
|
||||
(define-method get_user_data_dir
|
||||
(of-object "MooApp")
|
||||
(c-name "moo_app_get_user_data_dir")
|
||||
(return-type "char*")
|
||||
(parameters
|
||||
'("MooAppDataType" "type")
|
||||
)
|
||||
)
|
||||
|
||||
(define-method get_data_dirs
|
||||
(of-object "MooApp")
|
||||
(c-name "moo_app_get_data_dirs")
|
||||
(return-type "char*")
|
||||
(parameters
|
||||
'("MooAppDataType" "type")
|
||||
'("guint*" "n_dirs")
|
||||
)
|
||||
)
|
||||
|
||||
(define-method get_data_subdirs
|
||||
(of-object "MooApp")
|
||||
(c-name "moo_app_get_data_subdirs")
|
||||
(return-type "char*")
|
||||
(parameters
|
||||
'("const-char*" "subdir")
|
||||
'("MooAppDataType" "type")
|
||||
'("guint*" "n_dirs")
|
||||
)
|
||||
)
|
||||
|
|
|
@ -262,6 +262,16 @@
|
|||
)
|
||||
)
|
||||
|
||||
(define-enum DataDirType
|
||||
(in-module "Moo")
|
||||
(c-name "MooDataDirType")
|
||||
(gtype-id "MOO_TYPE_DATA_DIR_TYPE")
|
||||
(values
|
||||
'("share" "MOO_DATA_SHARE")
|
||||
'("lib" "MOO_DATA_LIB")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
;; From ../mooutils/moocombo.h
|
||||
|
||||
|
@ -2636,3 +2646,27 @@
|
|||
'("guint" "id")
|
||||
)
|
||||
)
|
||||
|
||||
(define-function get_user_data_dir
|
||||
(c-name "moo_get_user_data_dir")
|
||||
(return-type "char*")
|
||||
)
|
||||
|
||||
(define-function get_data_dirs
|
||||
(c-name "moo_get_data_dirs")
|
||||
(return-type "char**")
|
||||
(parameters
|
||||
'("MooDataDirType" "type")
|
||||
'("guint*" "n_dirs")
|
||||
)
|
||||
)
|
||||
|
||||
(define-function get_data_subdirs
|
||||
(c-name "moo_get_data_subdirs")
|
||||
(return-type "char**")
|
||||
(parameters
|
||||
'("const char*" "name")
|
||||
'("MooDataDirType" "type")
|
||||
'("guint*" "n_dirs")
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1073,3 +1073,233 @@ moo_menu_item_set_label (GtkWidget *item,
|
|||
else
|
||||
gtk_label_set_text (GTK_LABEL (label), text);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* data dirs
|
||||
*/
|
||||
|
||||
#ifdef __WIN32__
|
||||
static char *
|
||||
moo_get_app_dir (void)
|
||||
{
|
||||
static char *appdir;
|
||||
|
||||
if (!appdir)
|
||||
{
|
||||
gchar *appname = NULL;
|
||||
|
||||
if (G_WIN32_HAVE_WIDECHAR_API ())
|
||||
{
|
||||
wchar_t buf[MAX_PATH+1];
|
||||
|
||||
if (GetModuleFileNameW (GetModuleHandle (NULL), buf, G_N_ELEMENTS (buf)) > 0)
|
||||
appname = g_utf16_to_utf8 (buf, -1, NULL, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar buf[MAX_PATH+1];
|
||||
|
||||
if (GetModuleFileNameA (GetModuleHandle (NULL), buf, G_N_ELEMENTS (buf)) > 0)
|
||||
appname = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (appname)
|
||||
{
|
||||
appdir = g_path_get_basename (appname);
|
||||
g_free (utf8_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
appdir = g_strdup (".");
|
||||
}
|
||||
}
|
||||
|
||||
return appdir;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static char *
|
||||
moo_get_data_dir (MooDataDirType type)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
return moo_get_app_dir ();
|
||||
#else
|
||||
switch (type)
|
||||
{
|
||||
case MOO_DATA_SHARE:
|
||||
return g_strdup (MOO_DATA_DIR);
|
||||
case MOO_DATA_LIB:
|
||||
return g_strdup (MOO_LIB_DIR);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
moo_get_prgname (void)
|
||||
{
|
||||
static char *name;
|
||||
|
||||
if (!name)
|
||||
name = g_strdup (g_get_prgname ());
|
||||
|
||||
if (!name)
|
||||
{
|
||||
g_critical ("%s: program name not set", G_STRLOC);
|
||||
name = g_strdup ("ggap");
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
moo_get_user_data_dir (void)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
return g_build_filename (g_get_home_dir (), moo_get_prgname (), NULL);
|
||||
#else
|
||||
return g_strdup_printf ("%s/.%s", g_get_home_dir (), moo_get_prgname ());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
cmp_dirs (const char *dir1,
|
||||
const char *dir2)
|
||||
{
|
||||
g_return_val_if_fail (dir1 != NULL, FALSE);
|
||||
g_return_val_if_fail (dir2 != NULL, FALSE);
|
||||
/* XXX */
|
||||
return !strcmp (dir1, dir2);
|
||||
}
|
||||
|
||||
|
||||
char **
|
||||
moo_get_data_dirs (MooDataDirType type,
|
||||
guint *n_dirs)
|
||||
{
|
||||
const char *env[2];
|
||||
GPtrArray *dirs;
|
||||
GSList *list = NULL;
|
||||
guint i;
|
||||
|
||||
dirs = g_ptr_array_sized_new (3);
|
||||
env[0] = g_getenv ("MOO_APP_DIRS");
|
||||
env[1] = type == MOO_DATA_SHARE ? g_getenv ("MOO_DATA_DIRS") : g_getenv ("MOO_LIB_DIRS");
|
||||
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
const char *var = env[i];
|
||||
char **env_dirs, **p;
|
||||
|
||||
if (!var || !*var)
|
||||
continue;
|
||||
|
||||
#ifdef __WIN32__
|
||||
env_dirs = g_strsplit (var, ";", 0);
|
||||
p = moo_filenames_from_locale (env_dirs);
|
||||
g_strfreev (env_dirs);
|
||||
env_dirs = p;
|
||||
#else
|
||||
env_dirs = g_strsplit (var, ":", 0);
|
||||
#endif
|
||||
|
||||
for (p = env_dirs; p && *p; ++p)
|
||||
{
|
||||
if (**p)
|
||||
list = g_slist_prepend (list, *p);
|
||||
else
|
||||
g_free (*p);
|
||||
}
|
||||
|
||||
g_free (env_dirs);
|
||||
}
|
||||
|
||||
list = g_slist_prepend (list, moo_get_data_dir (type));
|
||||
list = g_slist_prepend (list, moo_get_user_data_dir ());
|
||||
|
||||
list = g_slist_reverse (list);
|
||||
|
||||
while (list)
|
||||
{
|
||||
gboolean found = FALSE;
|
||||
|
||||
if (!list->data)
|
||||
{
|
||||
list = g_slist_delete_link (list, list);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < dirs->len; ++i)
|
||||
{
|
||||
if (cmp_dirs (list->data, dirs->pdata[i]))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
g_ptr_array_add (dirs, list->data);
|
||||
else
|
||||
g_free (list->data);
|
||||
|
||||
list = g_slist_delete_link (list, list);
|
||||
}
|
||||
|
||||
if (n_dirs)
|
||||
*n_dirs = dirs->len;
|
||||
|
||||
g_ptr_array_add (dirs, NULL);
|
||||
return (char**) g_ptr_array_free (dirs, FALSE);
|
||||
}
|
||||
|
||||
|
||||
char **
|
||||
moo_get_data_subdirs (const char *subdir,
|
||||
MooDataDirType type,
|
||||
guint *n_dirs_p)
|
||||
{
|
||||
char **data_dirs, **dirs;
|
||||
guint n_dirs, i;
|
||||
|
||||
g_return_val_if_fail (subdir != NULL, NULL);
|
||||
|
||||
data_dirs = moo_get_data_dirs (type, &n_dirs);
|
||||
g_return_val_if_fail (data_dirs != NULL, NULL);
|
||||
|
||||
if (n_dirs_p)
|
||||
*n_dirs_p = n_dirs;
|
||||
|
||||
dirs = g_new0 (char*, n_dirs + 1);
|
||||
|
||||
for (i = 0; i < n_dirs; ++i)
|
||||
dirs[i] = g_build_filename (data_dirs[i], subdir, NULL);
|
||||
|
||||
return dirs;
|
||||
}
|
||||
|
||||
|
||||
GType
|
||||
moo_data_dir_type_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (!type)
|
||||
{
|
||||
static const GEnumValue values[] = {
|
||||
{ MOO_DATA_SHARE, (char*) "MOO_DATA_SHARE", (char*) "share" },
|
||||
{ MOO_DATA_LIB, (char*) "MOO_DATA_LIB", (char*) "lib" },
|
||||
{ 0, NULL, NULL },
|
||||
};
|
||||
|
||||
type = g_enum_register_static ("MooDataDirType", values);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -46,9 +46,30 @@ void moo_set_log_func_file (const char *log_file);
|
|||
void moo_set_log_func_silent (void);
|
||||
void moo_reset_log_func (void);
|
||||
|
||||
|
||||
void moo_segfault (void);
|
||||
|
||||
|
||||
#define MOO_TYPE_DATA_DIR_TYPE (moo_data_dir_type_get_type ())
|
||||
|
||||
typedef enum {
|
||||
MOO_DATA_SHARE,
|
||||
MOO_DATA_LIB
|
||||
} MooDataDirType;
|
||||
|
||||
GType moo_data_dir_type_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/* ~/.appname */
|
||||
char *moo_get_user_data_dir (void);
|
||||
/* $MOO_APP_DIR:$MOO_DATA_DIRS:$prefix/share/appname or
|
||||
$MOO_APP_DIR:$MOO_LIB_DIRS:$prefix/lib/appname */
|
||||
char **moo_get_data_dirs (MooDataDirType type,
|
||||
guint *n_dirs);
|
||||
char **moo_get_data_subdirs (const char *subdir,
|
||||
MooDataDirType type,
|
||||
guint *n_dirs);
|
||||
|
||||
|
||||
void moo_selection_data_set_pointer (GtkSelectionData *data,
|
||||
GdkAtom type,
|
||||
gpointer ptr);
|
||||
|
|
Loading…
Reference in New Issue