1 // --------------------------------------------------------------------
2 // Common code for all platforms
3 // --------------------------------------------------------------------
4 
5 #include <cstdio>
6 #include <cstdlib>
7 
8 // for version info only
9 #include "ipefonts.h"
10 #include <zlib.h>
11 
12 extern int luaopen_ipeui(lua_State *L);
13 extern int luaopen_appui(lua_State *L);
14 
15 // --------------------------------------------------------------------
16 
ipeIconDirectory()17 String ipeIconDirectory()
18 {
19   static String iconDir;
20   if (iconDir.empty()) {
21     const char *p = getenv("IPEICONDIR");
22 #ifdef IPEBUNDLE
23     String s(p ? p : Platform::ipeDir("icons"));
24 #else
25     String s(p ? p : IPEICONDIR);
26 #endif
27     if (s.right(1) != "/")
28       s += IPESEP;
29     iconDir = s;
30   }
31   return iconDir;
32 }
33 
traceback(lua_State * L)34 static int traceback (lua_State *L)
35 {
36   if (!lua_isstring(L, 1))  /* 'message' not a string? */
37     return 1;  /* keep it intact */
38   lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
39   lua_getfield(L, -1, "debug");
40   if (!lua_istable(L, -1)) {
41     lua_pop(L, 2);
42     return 1;
43   }
44   lua_getfield(L, -1, "traceback");
45   if (!lua_isfunction(L, -1)) {
46     lua_pop(L, 3);
47     return 1;
48   }
49   lua_pushvalue(L, 1);    // pass error message
50   lua_pushinteger(L, 2);  // skip this function and traceback
51   luacall(L, 2, 1);       // call debug.traceback
52   return 1;
53 }
54 
setup_config(lua_State * L,const char * var,const char * env,const char * conf)55 static void setup_config(lua_State *L, const char *var,
56 			 const char *env, const char *conf)
57 {
58   const char *p = env ? getenv(env) : nullptr;
59 #ifdef IPEBUNDLE
60   push_string(L, p ? p : Platform::ipeDir(conf));
61 #else
62   lua_pushstring(L, p ? p : conf);
63 #endif
64   lua_setfield(L, -2, var);
65 }
66 
setup_common_config(lua_State * L)67 static void setup_common_config(lua_State *L)
68 {
69   push_string(L, Fonts::freetypeVersion());
70   lua_setfield(L, -2, "freetype_version");
71   lua_pushfstring(L, "%s / %s", CAIRO_VERSION_STRING, cairo_version_string());
72   lua_setfield(L, -2, "cairo_version");
73   lua_pushliteral(L, ZLIB_VERSION);
74   lua_setfield(L, -2, "zlib_version");
75   push_string(L, Platform::spiroVersion());
76   lua_setfield(L, -2, "spiro_version");
77   push_string(L, Platform::gslVersion());
78   lua_setfield(L, -2, "gsl_version");
79 
80   push_string(L, Platform::latexDirectory());
81   lua_setfield(L, -2, "latexdir");
82   push_string(L, Platform::latexPath());
83   lua_setfield(L, -2, "latexpath");
84   push_string(L, ipeIconDirectory());
85   lua_setfield(L, -2, "icons");
86 
87   lua_pushfstring(L, "Ipe %d.%d.%d",
88 		  IPELIB_VERSION / 10000,
89 		  (IPELIB_VERSION / 100) % 100,
90 		  IPELIB_VERSION % 100);
91   lua_setfield(L, -2, "version");
92 
93   push_string(L, Platform::ipeDrive());
94   lua_setfield(L, -2, "ipedrive");
95 }
96 
97 // --------------------------------------------------------------------
98 
99 /* Replacement for Lua's tonumber function,
100    which is locale-dependent. */
ipe_tonumber(lua_State * L)101 static int ipe_tonumber(lua_State *L)
102 {
103   const char *s = luaL_checklstring(L, 1, nullptr);
104   int iValue;
105   double dValue;
106   int result = Platform::toNumber(s, iValue, dValue);
107   switch (result) {
108   case 2:
109     lua_pushnumber(L, dValue);
110     break;
111   case 1:
112     lua_pushinteger(L, iValue);
113     break;
114   case 0:
115   default:
116     lua_pushnil(L);
117   }
118   return 1;
119 }
120 
setup_lua()121 static lua_State *setup_lua()
122 {
123   lua_State *L = luaL_newstate();
124   luaL_openlibs(L);
125   luaopen_ipe(L);
126   luaopen_ipeui(L);
127   luaopen_appui(L);
128   return L;
129 }
130 
lua_run_ipe(lua_State * L,lua_CFunction fn)131 static bool lua_run_ipe(lua_State *L, lua_CFunction fn)
132 {
133   lua_pushcfunction(L, fn);
134   lua_setglobal(L, "mainloop");
135 
136   // run Ipe
137   lua_pushcfunction(L, traceback);
138   assert(luaL_loadstring(L, "require \"main\"") == 0);
139 
140   if (lua_pcallk(L, 0, 0, -2, 0, nullptr)) {
141     const char *errmsg = lua_tolstring(L, -1, nullptr);
142     fprintf(stderr, "%s\n", errmsg);
143     return false;
144   }
145   return true;
146 }
147 
148 // --------------------------------------------------------------------
149