aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormitchell <70453897+667e-11@users.noreply.github.com>2008-06-15 13:42:03 -0400
committermitchell <70453897+667e-11@users.noreply.github.com>2008-06-15 13:42:03 -0400
commite56e9f1c1a635bd205bfde9ff8120ad2e81274c0 (patch)
treebce6dea11c3947ac681234ac4167c436ecb34fde
parent0e1787a267d9a9ecf38e7eb88e01f1b585821185 (diff)
downloadtextadept-e56e9f1c1a635bd205bfde9ff8120ad2e81274c0.tar.gz
textadept-e56e9f1c1a635bd205bfde9ff8120ad2e81274c0.zip
Added doxygen documentation to source files.
-rw-r--r--src/find_replace.c27
-rw-r--r--src/lua_interface.c312
-rw-r--r--src/pm.c94
-rw-r--r--src/properties.h9
-rw-r--r--src/textadept.c152
5 files changed, 559 insertions, 35 deletions
diff --git a/src/find_replace.c b/src/find_replace.c
index 54c3f9e1..8564ff75 100644
--- a/src/find_replace.c
+++ b/src/find_replace.c
@@ -21,6 +21,9 @@ static bool
static void button_clicked(GtkWidget *button, gpointer);
+/**
+ * Creates the Find/Replace text frame.
+ */
GtkWidget* find_create_ui() {
findbox = gtk_table_new(2, 6, false);
@@ -81,6 +84,10 @@ GtkWidget* find_create_ui() {
return findbox;
}
+/**
+ * Toggles the focus between the Find/Replace frame and the current Scintilla
+ * window.
+ */
void find_toggle_focus() {
if (!GTK_WIDGET_HAS_FOCUS(findbox)) {
gtk_widget_show(findbox);
@@ -91,6 +98,10 @@ void find_toggle_focus() {
}
}
+/**
+ * Builds the integer flags for a Find/Replace depending on the options that are
+ * checked.
+ */
static int get_flags() {
int flags = 0;
if (toggled(match_case_opt)) flags |= SCFIND_MATCHCASE; // 2
@@ -99,8 +110,10 @@ static int get_flags() {
return flags;
}
-/** Find entry key event.
- * Enter - Find next or previous.
+/**
+ * Signal for a Find entry keypress.
+ * Currently handled keypresses:
+ * - Enter - Find next or previous.
*/
static bool fe_keypress(GtkWidget *, GdkEventKey *event, gpointer) {
// TODO: if incremental, call l_find()
@@ -110,8 +123,10 @@ static bool fe_keypress(GtkWidget *, GdkEventKey *event, gpointer) {
} else return false;
}
-/** Replace entry key event.
- * Enter - Find next or previous.
+/**
+ * Signal for a Replace entry keypress.
+ * Currently handled keypresses:
+ * - Enter - Find next or previous.
*/
static bool re_keypress(GtkWidget *, GdkEventKey *event, gpointer) {
if (event->keyval == 0xff0d) {
@@ -120,6 +135,10 @@ static bool re_keypress(GtkWidget *, GdkEventKey *event, gpointer) {
} else return false;
}
+/**
+ * Signal for a button click.
+ * Performs the appropriate action depending on the button clicked.
+ */
static void button_clicked(GtkWidget *button, gpointer) {
if (button == ra_button)
l_find_replace_all(find_text, repl_text, get_flags());
diff --git a/src/lua_interface.c b/src/lua_interface.c
index 8f7445e6..95a286e5 100644
--- a/src/lua_interface.c
+++ b/src/lua_interface.c
@@ -52,12 +52,21 @@ const char
*views_dne = "textadept.views doesn't exist or was overwritten.",
*buffers_dne = "textadept.buffers doesn't exist or was overwritten.";
+/**
+ * Inits or re-inits the Lua State.
+ * Populates the state with global variables and functions, then runs the
+ * 'core/init.lua' script.
+ * @param argc The number of command line parameters.
+ * @param argv The array of command line parameters.
+ * @param reinit Flag indicating whether or not to reinitialize the Lua State.
+ */
void l_init(int argc, char **argv, bool reinit) {
if (!reinit) {
lua = lua_open();
lua_newtable(lua);
for (int i = 0; i < argc; i++) {
- lua_pushstring(lua, argv[i]); lua_rawseti(lua, -2, i);
+ lua_pushstring(lua, argv[i]);
+ lua_rawseti(lua, -2, i);
}
lua_setfield(lua, LUA_REGISTRYINDEX, "arg");
lua_newtable(lua); lua_setfield(lua, LUA_REGISTRYINDEX, "buffers");
@@ -101,12 +110,21 @@ void l_init(int argc, char **argv, bool reinit) {
l_load_script("core/init.lua");
}
+/**
+ * Loads and runs a given Lua script.
+ * @param script_file The path of the Lua script relative to textadept_home.
+ */
void l_load_script(const char *script_file) {
char *script = g_strconcat(textadept_home, "/", script_file, NULL);
if (luaL_dofile(lua, script) != 0) l_handle_error(lua);
g_free(script);
}
+/**
+ * Retrieves the value of a given key in the global 'textadept' table.
+ * @param lua The Lua State.
+ * @param k The string key to lookup.
+ */
bool l_ta_get(LS *lua, const char *k) {
lua_getglobal(lua, "textadept");
lua_pushstring(lua, k); lua_rawget(lua, -2);
@@ -114,21 +132,40 @@ bool l_ta_get(LS *lua, const char *k) {
return lua_istable(lua, -1);
}
-// value is at stack top
+/**
+ * Sets the value for a given key in the global 'textadept' table.
+ * The value to set should be at the top of the stack in the Lua State.
+ * @param lua The Lua State.
+ * @param k The string key to set the value of.
+ */
void l_ta_set(LS *lua, const char *k) {
lua_getglobal(lua, "textadept");
lua_pushstring(lua, k); lua_pushvalue(lua, -3); lua_rawset(lua, -3);
lua_pop(lua, 2); // value and textadept
}
-// value is at stack top
+/**
+ * Sets the value for a given key in the LUA_REGISTRYINDEX and global
+ * 'textadept' table.
+ * The value to set should be at the top of the stack in the Lua State.
+ * @param lua The Lua State.
+ * @param k The string key to set the value of.
+ */
void l_reg_set(LS *lua, const char *k) {
lua_setfield(lua, LUA_REGISTRYINDEX, k);
lua_getfield(lua, LUA_REGISTRYINDEX, k);
l_ta_set(lua, k);
}
-/** Checks for a view and returns the GtkWidget associated with it. */
+/**
+ * Checks a specified stack element to see if it is a Scintilla window and
+ * returns it as a GtkWidget.
+ * @param lua The Lua State.
+ * @param narg Relative stack index to check for a Scintilla window.
+ * @param errstr Error string to use if the stack element is not a Scintilla
+ * window.
+ * Defaults to "View argument expected.".
+ */
static GtkWidget* l_checkview(LS *lua, int narg, const char *errstr=NULL) {
if (lua_type(lua, narg) == LUA_TTABLE) {
lua_pushstring(lua, "widget_pointer");
@@ -141,6 +178,10 @@ static GtkWidget* l_checkview(LS *lua, int narg, const char *errstr=NULL) {
return editor;
}
+/**
+ * Adds a Scintilla window to the global 'views' table with a metatable.
+ * @param editor The Scintilla window to add.
+ */
void l_add_scintilla_window(GtkWidget *editor) {
if (!l_ta_get(lua, "views")) luaL_error(lua, views_dne);
lua_newtable(lua);
@@ -155,6 +196,10 @@ void l_add_scintilla_window(GtkWidget *editor) {
lua_pop(lua, 1); // views
}
+/**
+ * Removes a Scintilla window from the global 'views' table.
+ * @param editor The Scintilla window to remove.
+ */
void l_remove_scintilla_window(GtkWidget *editor) {
lua_newtable(lua);
if (!l_ta_get(lua, "views")) luaL_error(lua, views_dne);
@@ -165,6 +210,15 @@ void l_remove_scintilla_window(GtkWidget *editor) {
l_reg_set(lua, "views");
}
+/**
+ * Changes focus a Scintilla window in the global 'views' table.
+ * @param editor The currently focused Scintilla window.
+ * @param n The index of the window in the 'views' table to focus.
+ * @param absolute Flag indicating whether or not the index specified in 'views'
+ * is absolute. If false, focuses the window relative to the currently focused
+ * window for the given index.
+ * Defaults to true.
+ */
void l_goto_scintilla_window(GtkWidget *editor, int n, bool absolute) {
if (!l_ta_get(lua, "views")) luaL_error(lua, views_dne);
if (!absolute) {
@@ -187,6 +241,10 @@ void l_goto_scintilla_window(GtkWidget *editor, int n, bool absolute) {
lua_pop(lua, 2); // view table and views
}
+/**
+ * Sets the global 'view' variable to be the specified Scintilla window.
+ * @param editor The Scintilla window to set 'view' to.
+ */
void l_set_view_global(GtkWidget *editor) {
if (!l_ta_get(lua, "views")) luaL_error(lua, views_dne);
lua_pushnil(lua);
@@ -199,7 +257,14 @@ void l_set_view_global(GtkWidget *editor) {
lua_pop(lua, 1); // views
}
-/** Checks for a buffer and returns the doc_pointer associated with it. */
+/**
+ * Checks a specified element to see if it is a buffer table and returns the
+ * Scintilla document pointer associated with it.
+ * @param lua The Lua State.
+ * @param narg Relative stack index to check for a buffer table.
+ * @param errstr Error string to use if the stack element is not a buffer table.
+ * Defaults to "Buffer argument expected.".
+ */
static sptr_t l_checkdocpointer(LS *lua, int narg, const char *errstr=NULL) {
if (lua_type(lua, narg) == LUA_TTABLE) {
lua_pushstring(lua, "doc_pointer");
@@ -212,6 +277,10 @@ static sptr_t l_checkdocpointer(LS *lua, int narg, const char *errstr=NULL) {
return doc;
}
+/**
+ * Adds a Scintilla document to the global 'buffers' table with a metatable.
+ * @param doc The Scintilla document to add.
+ */
int l_add_scintilla_buffer(sptr_t doc) {
if (!l_ta_get(lua, "buffers")) luaL_error(lua, buffers_dne);
lua_newtable(lua);
@@ -227,8 +296,13 @@ int l_add_scintilla_buffer(sptr_t doc) {
return index;
}
+/**
+ * Removes a Scintilla document from the global 'buffers' table.
+ * If any views currently show the document to be removed, change the documents
+ * they show first.
+ * @param doc The Scintilla buffer to remove.
+ */
void l_remove_scintilla_buffer(sptr_t doc) {
- // Switch documents for all views that show the current document.
if (!l_ta_get(lua, "views")) luaL_error(lua, views_dne);
lua_pushnil(lua);
while (lua_next(lua, -2)) {
@@ -246,6 +320,11 @@ void l_remove_scintilla_buffer(sptr_t doc) {
l_reg_set(lua, "buffers");
}
+/**
+ * Retrieves the index in the global 'buffers' table for a given Scintilla
+ * document.
+ * @param doc The Scintilla document to get the index of.
+ */
unsigned int l_get_docpointer_index(sptr_t doc) {
if (!l_ta_get(lua, "buffers")) luaL_error(lua, buffers_dne);
unsigned int idx = 1;
@@ -264,6 +343,19 @@ unsigned int l_get_docpointer_index(sptr_t doc) {
{ lua_pushstring(lua, k); lua_pushinteger(lua, v); lua_rawset(lua, -3); }
#define l_get_bufferp(k, i) \
{ lua_pushstring(lua, k); lua_rawget(lua, i < 0 ? i - 1 : i); }
+
+/**
+ * Changes a Scintilla window's document to one in the global 'buffers' table.
+ * Before doing so, it saves the scroll and caret positions in the current
+ * Scintilla document. Then when the new document is shown, its scroll and caret
+ * positions are restored.
+ * @param editor The Scintilla window to change the document of.
+ * @param n The index of the document in 'buffers' to focus.
+ * @param absolute Flag indicating whether or not the index specified in 'views'
+ * is absolute. If false, focuses the document relative to the currently
+ * focused document for the given index.
+ * Defaults to true.
+ */
void l_goto_scintilla_buffer(GtkWidget *editor, int n, bool absolute) {
if (!l_ta_get(lua, "buffers")) luaL_error(lua, buffers_dne);
ScintillaObject *sci = SCINTILLA(editor);
@@ -301,6 +393,11 @@ void l_goto_scintilla_buffer(GtkWidget *editor, int n, bool absolute) {
lua_pop(lua, 2); // buffer table and buffers
}
+/**
+ * Sets the global 'buffer' variable to be the document in the specified
+ * Scintilla object.
+ * @param sci The Scintilla object whose buffer is to be 'buffer'.
+ */
void l_set_buffer_global(ScintillaObject *sci) {
sptr_t doc = SS(sci, SCI_GETDOCPOINTER);
if (!l_ta_get(lua, "buffers")) luaL_error(lua, buffers_dne);
@@ -314,6 +411,11 @@ void l_set_buffer_global(ScintillaObject *sci) {
lua_pop(lua, 1); // buffers
}
+/**
+ * Closes the Lua State.
+ * Unsplits all Scintilla windows recursively, removes all Scintilla documents,
+ * and deletes the last Scintilla window before closing the state.
+ */
void l_close() {
closing = true;
while (unsplit_window(focused_editor));
@@ -330,6 +432,12 @@ void l_close() {
// Utility Functions
+/**
+ * Recurses through a Lua table, setting each of its keys and values to nil,
+ * effectively clearing the table.
+ * @param lua The Lua State.
+ * @param abs_index The absolute stack index of the table to clear.
+ */
static void clear_table(LS *lua, int abs_index) {
lua_pushnil(lua);
while (lua_next(lua, abs_index)) {
@@ -339,6 +447,12 @@ static void clear_table(LS *lua, int abs_index) {
}
}
+/**
+ * Checks if the Scintilla document of the buffer table at the index specified
+ * is the document of the focused Scintilla window.
+ * @param lua The Lua State.
+ * @param narg The relative stack position of the buffer table.
+ */
static void l_check_focused_buffer(LS *lua, int narg) {
ScintillaObject *sci = SCINTILLA(focused_editor);
sptr_t cur_doc = SS(sci, SCI_GETDOCPOINTER);
@@ -346,6 +460,13 @@ static void l_check_focused_buffer(LS *lua, int narg) {
luaL_error(lua, "The indexed buffer is not the focused one.");
}
+/**
+ * Checks whether or not a table in the global 'textadept' table has the
+ * specified key and returns true or false.
+ * @param lua The Lua State.
+ * @param table The table in 'textadept' to check for key in.
+ * @param key String key to check for in table.
+ */
static bool l_is_ta_table_key(LS *lua, const char *table, const char *key) {
if (l_ta_get(lua, table)) {
lua_getfield(lua, -1, key);
@@ -356,6 +477,12 @@ static bool l_is_ta_table_key(LS *lua, const char *table, const char *key) {
return false;
}
+/**
+ * Checks whether or not a table in the global 'textadept' table has the
+ * specified function and returns true or false.
+ * @param table The table in 'textadept' to check for function in.
+ * @param function String function name to check for in table.
+ */
bool l_is_ta_table_function(const char *table, const char *function) {
if (l_ta_get(lua, table)) {
lua_getfield(lua, -1, function);
@@ -366,6 +493,17 @@ bool l_is_ta_table_function(const char *table, const char *function) {
return false;
}
+/**
+ * Calls a Lua function with a number of arguments and expected return values.
+ * The last argument is at the stack top, and each argument in reverse order is
+ * one element lower on the stack with the Lua function being under the first
+ * argument.
+ * @param nargs The number of arguments to pass to the Lua function to call.
+ * @param retn The number of expected return values. Defaults to 0.
+ * @param keep_return Flag indicating whether or not to keep the return values
+ * at the top of the stack. If false, discards the return values.
+ * Defaults to false.
+ */
bool l_call_function(int nargs, int retn=0, bool keep_return=false) {
int ret = lua_pcall(lua, nargs, retn, 0);
if (ret == 0) {
@@ -376,6 +514,12 @@ bool l_call_function(int nargs, int retn=0, bool keep_return=false) {
return false;
}
+/**
+ * Performs a Lua rawget on a table at a given stack index and returns an int.
+ * @param lua The Lua State.
+ * @param index The relative index of the table to rawget from.
+ * @param n The index in the table to rawget.
+ */
static int l_rawgeti_int(LS *lua, int index, int n) {
lua_rawgeti(lua, index, n);
int ret = static_cast<int>(lua_tointeger(lua, -1));
@@ -383,6 +527,12 @@ static int l_rawgeti_int(LS *lua, int index, int n) {
return ret;
}
+/**
+ * Performs a Lua rawget on a table at a given stack index and returns a string.
+ * @param lua The Lua State.
+ * @param index The relative index of the table to rawget from.
+ * @param k String key in the table to rawget.
+ */
static const char* l_rawget_str(LS *lua, int index, const char *k) {
lua_pushstring(lua, k); lua_rawget(lua, index);
const char *str = lua_tostring(lua, -1);
@@ -390,7 +540,14 @@ static const char* l_rawget_str(LS *lua, int index, const char *k) {
return str;
}
-/** Get a long for Scintilla w or l parameter based on type. */
+/**
+ * Convert the stack element at a specified index to a Scintilla w and/or l long
+ * parameter based on type.
+ * @param lua The Lua State.
+ * @param type The Lua type the top stack element is.
+ * @param arg_idx The initial stack index to start converting at. It is
+ * incremented as parameters are read from the stack.
+ */
static long l_toscintillaparam(LS *lua, int type, int &arg_idx) {
if (type == tSTRING)
return reinterpret_cast<long>(lua_tostring(lua, arg_idx++));
@@ -405,6 +562,14 @@ static long l_toscintillaparam(LS *lua, int type, int &arg_idx) {
else return 0;
}
+/**
+ * Creates a GtkMenu from a table at the top of the Lua stack.
+ * The table has a key 'title' and a numeric list of subitems.
+ * @param lua The Lua State.
+ * @param callback A GCallback associated with each menu item.
+ * @param submenu Flag indicating whether or not this menu is a submenu.
+ * Defaults to false.
+ */
GtkWidget* l_create_gtkmenu(LS *lua, GCallback callback, bool submenu=false) {
GtkWidget *menu = gtk_menu_new(), *menu_item = 0, *submenu_root = 0;
const char *label;
@@ -434,7 +599,12 @@ GtkWidget* l_create_gtkmenu(LS *lua, GCallback callback, bool submenu=false) {
// Notification/event handlers
-// error message is at stack top
+/**
+ * Handles a Lua error.
+ * The main error message is at the top of the Lua stack.
+ * @param lua The Lua State.
+ * @param errmsg An additional error message to display. Defaults to NULL.
+ */
void l_handle_error(LS *lua, const char *errmsg) {
if (focused_editor && l_is_ta_table_function("events", "error")) {
l_insert(lua, -1); // shift error message down
@@ -447,16 +617,32 @@ void l_handle_error(LS *lua, const char *errmsg) {
lua_settop(lua, 0);
}
+/**
+ * Handles a Textadept event.
+ * @param s String event name.
+ */
bool l_handle_event(const char *s) {
return l_is_ta_table_function("events", s) ? l_call_function(0, 1) : true;
}
+/**
+ * Handles a Textadept event.
+ * @param s String event name.
+ * @param arg String first argument.
+ */
bool l_handle_event(const char *s, const char *arg) {
if (!l_is_ta_table_function("events", s)) return false;
lua_pushstring(lua, arg);
return l_call_function(1, 1);
}
+/**
+ * Handles a Textadept keypress.
+ * @param keyval The key value of the key pressed.
+ * @param shift Flag indicating whether or not the shift modifier was held.
+ * @param control Flag indicating whether or not the control modifier was held.
+ * @param alt Flag indicating whether or not the alt modifier was held.
+ */
bool l_handle_keypress(int keyval, bool shift, bool control, bool alt) {
if (!l_is_ta_table_function("events", "keypress")) return false;
lua_pushinteger(lua, keyval);
@@ -468,6 +654,11 @@ bool l_handle_keypress(int keyval, bool shift, bool control, bool alt) {
#define l_scn_int(i, n) { lua_pushinteger(lua, i); lua_setfield(lua, -2, n); }
#define l_scn_str(s, n) { lua_pushstring(lua, s); lua_setfield(lua, -2, n); }
+
+/**
+ * Handles a Scintilla notification.
+ * @param n The Scintilla notification struct.
+ */
void l_handle_scnnotification(SCNotification *n) {
if (!l_is_ta_table_function("events", "notification")) return;
lua_newtable(lua);
@@ -496,6 +687,10 @@ void l_handle_scnnotification(SCNotification *n) {
l_call_function(1);
}
+/**
+ * Executes a given command string as Lua code.
+ * @param command Lua code to execute.
+ */
void l_ta_command(const char *command) {
int top = lua_gettop(lua);
if (luaL_dostring(lua, command) == 0) {
@@ -506,7 +701,16 @@ void l_ta_command(const char *command) {
// Project Manager
-// full_path is at stack top if entry_text is NULL
+/**
+ * Requests contents for the Project Manager.
+ * @param entry_text The text in the Project Manager Entry. If NULL, the full
+ * path table is at the top of the Lua stack.
+ * @param expanding Flag indicating whether or not a treenode is being expanded.
+ * If true, the tree is walked up from the node to top creating a full path
+ * table at the stack top to be used essentially as entry_text.
+ * Defaults to false.
+ * @see l_pm_get_full_path
+ */
bool l_pm_get_contents_for(const char *entry_text, bool expanding) {
if (!l_is_ta_table_function("pm", "get_contents_for")) return false;
if (entry_text) {
@@ -518,7 +722,13 @@ bool l_pm_get_contents_for(const char *entry_text, bool expanding) {
return l_call_function(2, 1, true);
}
-// table is at stack top
+/**
+ * Populates the Project Manager pane with the contents of a Lua table at the
+ * stack top.
+ * @param initial_iter The initial GtkTreeIter. If not NULL, it is a treenode
+ * being expanded and the contents will be added to that expanding node.
+ * Defaults to NULL.
+ */
void l_pm_populate(GtkTreeIter *initial_iter) {
GtkTreeIter iter, child;
if (!lua_istable(lua, -1))
@@ -549,8 +759,13 @@ void l_pm_populate(GtkTreeIter *initial_iter) {
} lua_pop(lua, 1); // returned table
}
+/**
+ * For a Project Manager given node, get the full path to that node.
+ * It leaves a full path table at the top of the Lua stack.
+ * @param path The GtkTreePath of the node.
+ */
void l_pm_get_full_path(GtkTreePath *path) {
- lua_newtable(lua); // will be at stack top
+ lua_newtable(lua);
lua_pushstring(lua, gtk_entry_get_text(GTK_ENTRY(pm_entry)));
lua_rawseti(lua, -2, 1);
if (!path) return;
@@ -566,6 +781,11 @@ void l_pm_get_full_path(GtkTreePath *path) {
}
}
+/**
+ * Requests and pops up a context menu for the Project Manager.
+ * @param event The mouse button event.
+ * @param callback The GCallback associated with each menu item.
+ */
void l_pm_popup_context_menu(GdkEventButton *event, GCallback callback) {
if (!l_is_ta_table_function("pm", "get_context_menu")) return;
GtkTreeIter iter;
@@ -589,14 +809,22 @@ void l_pm_popup_context_menu(GdkEventButton *event, GCallback callback) {
} else warn("pm.get_context_menu return was not a table.");
}
-// full_path is at stack top
+/**
+ * Performs an action for an activated item in the Project Manager.
+ * The full path table for the item is at the top of the Lua stack.
+ */
void l_pm_perform_action() {
if (!l_is_ta_table_function("pm", "perform_action")) return;
l_insert(lua, -1); // shift full_path down
l_call_function(1);
}
-// full_path is at stack top
+/**
+ * Performs a selected menu action from an item's context menu in the Project
+ * Manager.
+ * The full path table for the item is at the top of the Lua stack.
+ * @param menu_item The label text for the menu item clicked.
+ */
void l_pm_perform_menu_action(const char *menu_item) {
if (!l_is_ta_table_function("pm", "perform_menu_action")) return;
l_insert(lua, -1); // shift full_path down
@@ -607,6 +835,13 @@ void l_pm_perform_menu_action(const char *menu_item) {
// Find/Replace
+/**
+ * Finds text in the current document.
+ * @param ftext The text to find.
+ * @param flags Integer flags for the find.
+ * @param next Flag indicating whether or not to find next. If false, finds
+ * previous matches.
+ */
void l_find(const char *ftext, int flags, bool next) {
if (!l_is_ta_table_function("find", "find")) return;
lua_pushstring(lua, ftext);
@@ -615,12 +850,22 @@ void l_find(const char *ftext, int flags, bool next) {
l_call_function(3);
}
+/**
+ * Replaces text in the current document.
+ * @param rtext The text to replace the found text with.
+ */
void l_find_replace(const char *rtext) {
if (!l_is_ta_table_function("find", "replace")) return;
lua_pushstring(lua, rtext);
l_call_function(1);
}
+/**
+ * Replaces all found text in the current document.
+ * @param ftext The text to find.
+ * @param rtext The text to replace the found text with.
+ * @param flags Integer flags for the find.
+ */
void l_find_replace_all(const char *ftext, const char *rtext, int flags) {
if (!l_is_ta_table_function("find", "replace_all")) return;
lua_pushstring(lua, ftext);
@@ -631,10 +876,15 @@ void l_find_replace_all(const char *ftext, const char *rtext, int flags) {
// Lua functions (stack maintenence is unnecessary)
-/** Calls Scintilla returning appropriate values.
- * The p1, p2, and rt types are integer types of the w, l, and return
- * parameters respectively. arg is the Lua stack index where user arguments
- * begin. The appropriate value(s) are returned to Lua.
+/**
+ * Calls Scintilla with appropriate parameters and returs appropriate values.
+ * @param lua The Lua State.
+ * @param sci The Scintilla object to call.
+ * @param msg The integer message index to call Scintilla with.
+ * @param p1_type The Lua type of p1, the Scintilla w parameter.
+ * @param p2_type The Lua type of p2, the Scintilla l parameter.
+ * @param rt_type The Lua type of the Scintilla return parameter.
+ * @param arg The index on the Lua stack where arguments to Scintilla begin.
*/
LF l_call_scintilla(LS *lua, ScintillaObject *sci, int msg,
int p1_type, int p2_type, int rt_type, int arg) {
@@ -672,6 +922,11 @@ LF l_call_scintilla(LS *lua, ScintillaObject *sci, int msg,
return lua_gettop(lua) - arg;
}
+/**
+ * Calls a Scintilla buffer function with upvalues from a closure.
+ * @param lua The Lua State.
+ * @see l_buffer_mt_index
+ */
LF l_call_buffer_function(LS *lua) {
int sci_idx = lua_upvalueindex(1); // closure from __index
ScintillaObject *sci =
@@ -684,6 +939,14 @@ LF l_call_buffer_function(LS *lua) {
return l_call_scintilla(lua, sci, msg, p1_type, p2_type, rt_type, 2);
}
+/**
+ * Metatable index for a buffer table.
+ * If the key is a Scintilla buffer function, push a closure so it can be called
+ * as a function. If the key is a non-indexable buffer property, call Scintilla
+ * to get it. If the key is an indexible buffer property, push a table with a
+ * metatable to access buffer property indices.
+ * @param lua The Lua State.
+ */
LF l_buffer_mt_index(LS *lua) {
ScintillaObject *sci = SCINTILLA(focused_editor);
const char *key = luaL_checkstring(lua, 2);
@@ -710,11 +973,14 @@ LF l_buffer_mt_index(LS *lua) {
return 1;
}
-/** Helper function for the buffer property metatable.
- * n indicates a getter or setter (1 or 2) and arg is the Lua stack index
- * where user arguments begin. For setting buffer properties, it is 3 because
- * the index is not an argument, but for getting and setting indexed buffer
- * properties it is 2 because the index is an argument.
+/**
+ * Helper function for the buffer property metatable.
+ * @param lua The Lua State.
+ * @param n 1 for getter property, 2 for setter.
+ * @param prop String property name.
+ * @param arg The index on the Lua stack where arguments to Scintilla begin.
+ * For setter properties, it is 3 because the index is not an argument. For
+ * getter and setter properties, it is 2 because the index is an argument.
*/
LF l_bufferp_mt_(LS *lua, int n, const char *prop, int arg) {
ScintillaObject *sci = SCINTILLA(focused_editor);
@@ -856,7 +1122,7 @@ LF l_find_mt_newindex(LS *lua) {
return 0;
}
-// Lua CFunctions
+// Lua CFunctions. For documentation, consult the LuaDoc.
LF l_cf_ta_buffer_new(LS *lua) {
new_scintilla_buffer(SCINTILLA(focused_editor), true, true);
diff --git a/src/pm.c b/src/pm.c
index b9d23835..79c8de51 100644
--- a/src/pm.c
+++ b/src/pm.c
@@ -23,6 +23,12 @@ static bool pm_button_press(GtkTreeView *, GdkEventButton *event, gpointer);
static bool pm_popup_menu(GtkWidget *, gpointer);
static void pm_menu_activate(GtkWidget *menu_item, gpointer);
+/**
+ * Creates the Project Manager pane.
+ * It consists of an entry box and a treeview called 'textadept-pm-entry' and
+ * 'textadept-pm-view' respectively for styling via gtkrc. The treeview model
+ * consists of a gdk-pixbuf for icons and markup text.
+ */
GtkWidget* pm_create_ui() {
pm_container = gtk_vbox_new(false, 1);
@@ -72,6 +78,14 @@ GtkWidget* pm_create_ui() {
return pm_container;
}
+/**
+ * Requests contents for a Project Manager parent node being opened.
+ * Since parents have a dummy child by default just to indicate they are indeed
+ * parents, that dummy child is removed now.
+ * @param iter The parent GtkTreeIter.
+ * @param path The parent GtkTreePath.
+ * @see l_pm_get_contents_for
+ */
void pm_open_parent(GtkTreeIter *iter, GtkTreePath *path) {
l_pm_get_full_path(path);
if (l_pm_get_contents_for(NULL, true)) l_pm_populate(iter);
@@ -84,6 +98,12 @@ void pm_open_parent(GtkTreeIter *iter, GtkTreePath *path) {
g_free(filename);
}
+/**
+ * Removes all Project Manager children from a parent node being closed.
+ * It does add a dummy child by default to indicate the parent is indeed a
+ * parent. It will be removed when the parent is opened.
+ * @param iter The parent GtkTreeIter.
+ */
void pm_close_parent(GtkTreeIter *iter, GtkTreePath *) {
GtkTreeIter child;
gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(pm_store), &child, iter, 0);
@@ -93,6 +113,12 @@ void pm_close_parent(GtkTreeIter *iter, GtkTreePath *) {
gtk_tree_store_set(pm_store, &child, 1, "\0dummy", -1);
}
+/**
+ * Performs the appropriate action on a selected Project Manager node.
+ * If the node is a collapsed parent, it is expanded; otherwise the parent is
+ * collapsed. If the node is not a parent at all, a Lua action is performed.
+ * @see l_pm_perform_action
+ */
void pm_activate_selection() {
GtkTreeIter iter;
GtkTreePath *path;
@@ -111,10 +137,20 @@ void pm_activate_selection() {
gtk_tree_path_free(path);
}
+/**
+ * Pops up a context menu for the selected Project Manager node.
+ * @param event The mouse button event.
+ * @see l_pm_popup_context_menu
+ */
void pm_popup_context_menu(GdkEventButton *event) {
l_pm_popup_context_menu(event, G_CALLBACK(pm_menu_activate));
}
+/**
+ * Performs a Lua action for a selected Project Manager menu item.
+ * @param menu_item The menu item.
+ * @see l_pm_perform_menu_action
+ */
void pm_process_selected_menu_item(GtkWidget *menu_item) {
GtkWidget *label = gtk_bin_get_child(GTK_BIN(menu_item));
const char *text = gtk_label_get_text(GTK_LABEL(label));
@@ -125,11 +161,23 @@ void pm_process_selected_menu_item(GtkWidget *menu_item) {
l_pm_perform_menu_action(text);
}
+/**
+ * Toggles the focus between the Project Manager and the current Scintilla
+ * window.
+ */
void pm_toggle_focus() {
gtk_widget_grab_focus(
GTK_WIDGET_HAS_FOCUS(focused_editor) ? pm_entry : focused_editor);
}
+/**
+ * When searching the Project Manager treeview, matches are tree items that
+ * contain the search text as a substring.
+ * @param model The GtkTreeModel for the treeview.
+ * @param col The column number to use for comparing search text to.
+ * @param key The search text.
+ * @param iter The GtkTreeIter for each tree node being compared.
+ */
static int pm_search_equal_func(GtkTreeModel *model, int col, const char *key,
GtkTreeIter *iter, gpointer) {
const char *text;
@@ -137,6 +185,12 @@ static int pm_search_equal_func(GtkTreeModel *model, int col, const char *key,
return strstr(text, key) == NULL; // false is really a match like strcmp
}
+/**
+ * Sorts the Project Manager treeview case sensitively.
+ * @param model The GtkTreeModel for the treeview.
+ * @param a The GtkTreeIter for one tree node being compared.
+ * @param b The GtkTreeIter for the other tree node being compared.
+ */
static int pm_sort_iter_compare_func(GtkTreeModel *model, GtkTreeIter *a,
GtkTreeIter *b, gpointer) {
const char *a_text, *b_text;
@@ -149,14 +203,22 @@ static int pm_sort_iter_compare_func(GtkTreeModel *model, GtkTreeIter *a,
}
// Signals
+
+/**
+ * Signal for the activation of the Project Manager entry.
+ * Requests contents for the treeview.
+ * @see l_pm_get_contents_for
+ */
static void pm_entry_activated(GtkWidget *widget, gpointer) {
const char *entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
if (l_pm_get_contents_for(entry_text)) l_pm_populate();
}
-/** Project manager key events.
- * Ctrl+Tab - Refocuses the Scintilla view.
- * Escape - Refocuses the Scintilla view.
+/**
+ * Signal for a Project Manager keypress.
+ * Currently handled keypresses:
+ * - Ctrl+Tab - Refocuses the Scintilla view.
+ * - Escape - Refocuses the Scintilla view.
*/
static bool pm_keypress(GtkWidget *, GdkEventKey *event, gpointer) {
if (event->keyval == 0xff09 && event->state == GDK_CONTROL_MASK ||
@@ -166,30 +228,56 @@ static bool pm_keypress(GtkWidget *, GdkEventKey *event, gpointer) {
} else return false;
}
+/**
+ * Signal for a Project Manager parent expansion.
+ * @see pm_open_parent
+ */
static void pm_row_expanded(GtkTreeView *, GtkTreeIter *iter,
GtkTreePath *path, gpointer) {
pm_open_parent(iter, path);
}
+/**
+ * Signal for a Project Manager parent collapse.
+ * @see pm_close_parent
+ */
static void pm_row_collapsed(GtkTreeView *, GtkTreeIter *iter,
GtkTreePath *path, gpointer) {
pm_close_parent(iter, path);
}
+/**
+ * Signal for the activation of a Project Manager node.
+ * @see pm_activate_selection
+ */
static void pm_row_activated(GtkTreeView *, GtkTreePath *, GtkTreeViewColumn *,
gpointer) {
pm_activate_selection();
}
+/**
+ * Signal for a Project Manager mouse click.
+ * If it is a right-click, popup a context menu for the selected node.
+ * @see pm_popup_context_menu
+ */
static bool pm_button_press(GtkTreeView *, GdkEventButton *event, gpointer) {
if (event->type != GDK_BUTTON_PRESS || event->button != 3) return false;
pm_popup_context_menu(event); return true;
}
+/**
+ * Signal for popping up a Project Manager context menu.
+ * Typically Shift+F10 activates this event.
+ * @see pm_popup_context_menu
+ */
static bool pm_popup_menu(GtkWidget *, gpointer) {
pm_popup_context_menu(NULL); return true;
}
+/**
+ * Signal for a selected Project Manager menu item.
+ * @see pm_process_selected_menu_item
+ */
static void pm_menu_activate(GtkWidget *menu_item, gpointer) {
pm_process_selected_menu_item(menu_item);
}
diff --git a/src/properties.h b/src/properties.h
index 24f10507..0ea11a2e 100644
--- a/src/properties.h
+++ b/src/properties.h
@@ -8,6 +8,10 @@
#define sp(k, v) SSS(sci, SCI_SETPROPERTY, k, v)
#define color(r, g, b) r | (g << 8) | (b << 16)
+/**
+ * Sets the default properties for a Scintilla window.
+ * @param sci The Scintilla window to set default properties for.
+ */
void set_default_editor_properties(ScintillaObject *sci) {
sp("lexer.lua.home", "/usr/share/textadept/lexers/");
sp("lexer.lua.script", "/usr/share/textadept/lexers/lexer.lua");
@@ -64,6 +68,11 @@ void set_default_editor_properties(ScintillaObject *sci) {
SS(sci, SCI_SETCARETSTICKY, 0);
}
+/**
+ * Sets the default properties for a Scintilla document.
+ * @param sci The Scintilla window containing the document to set default
+ * properties for.
+ */
void set_default_buffer_properties(ScintillaObject *sci) {
sp("fold", "1");
sp("fold.by.indentation", "1");
diff --git a/src/textadept.c b/src/textadept.c
index 8ae255f4..e05acc36 100644
--- a/src/textadept.c
+++ b/src/textadept.c
@@ -18,6 +18,13 @@ static bool w_focus(GtkWidget*, GdkEventFocus *, gpointer);
static bool w_keypress(GtkWidget*, GdkEventKey *event, gpointer);
static bool w_exit(GtkWidget*, GdkEventAny*, gpointer);
+/**
+ * Runs Textadept.
+ * Inits the Lua State, creates the user interface, and loads the core/init.lua
+ * script.
+ * @param argc The number of command line params.
+ * @param argv The array of command line params.
+ */
int main(int argc, char **argv) {
gtk_init(&argc, &argv);
l_init(argc, argv, false);
@@ -27,6 +34,19 @@ int main(int argc, char **argv) {
return 0;
}
+/**
+ * Creates the user interface.
+ * The UI consists of:
+ * - A menubar initially hidden and empty. It should be populated by script
+ * and then shown.
+ * - A side pane. It contains a treeview for hierarchical data sets, such as
+ * a file structure for project management.
+ * - A frame for Scintilla windows.
+ * - A find text frame initially hidden.
+ * - A command entry initially hidden. This entry accepts and runs Lua code
+ * in the current Lua state.
+ * - Two status bars: one for notifications, the other for document status.
+ */
void create_ui() {
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 500, 400);
@@ -70,6 +90,18 @@ void create_ui() {
gtk_widget_grab_focus(editor);
}
+/**
+ * Creates a new Scintilla window.
+ * The Scintilla window is the GTK widget that displays a Scintilla buffer.
+ * The window's default properties are set via 'set_default_editor_properties'.
+ * Generates a 'view_new' event.
+ * @param buffer_id A Scintilla buffer ID to load into the new window. If NULL,
+ * creates a new Scintilla buffer and loads it into the new window.
+ * Defaults to NULL.
+ * @return the Scintilla window.
+ * @see set_default_editor_properties
+ * @see l_add_scintilla_window
+ */
GtkWidget* new_scintilla_window(sptr_t buffer_id) {
GtkWidget *editor = scintilla_new();
gtk_widget_set_size_request(editor, 1, 1); // minimum size
@@ -88,11 +120,36 @@ GtkWidget* new_scintilla_window(sptr_t buffer_id) {
return editor;
}
+/**
+ * Removes a Scintilla window.
+ * @param editor The Scintilla window to remove.
+ * @see l_remove_scintilla_window
+ */
void remove_scintilla_window(GtkWidget *editor) {
l_remove_scintilla_window(editor);
gtk_widget_destroy(editor);
}
+/**
+ * Creates a new Scintilla buffer for a newly created Scintilla window.
+ * The buffer's default properties are set via 'set_default_buffer_properties',
+ * but the default style is set here.
+ * Generates a 'buffer_new' event.
+ * @param sci The ScintillaObject to associate the buffer with.
+ * @param create Flag indicating whether or not to create a buffer. If false,
+ * the ScintillaObject already has a buffer associated with it (typically
+ * because new_scintilla_window was passed a non-NULL buffer_id).
+ * Defaults to true.
+ * @param addref Flag indicating whether or not to add a reference to the buffer
+ * in the ScintillaObject when create is false. This is necessary for creating
+ * Scintilla windows in split views. If a buffer appears in two separate
+ * Scintilla windows, that buffer should have multiple references so when one
+ * Scintilla window closes, the buffer is not deleted because its reference
+ * count is not zero.
+ * Defaults to true.
+ * @see set_default_buffer_properties
+ * @see l_add_scintilla_buffer
+ */
void new_scintilla_buffer(ScintillaObject *sci, bool create, bool addref) {
sptr_t doc;
doc = SS(sci, SCI_GETDOCPOINTER);
@@ -115,11 +172,24 @@ void new_scintilla_buffer(ScintillaObject *sci, bool create, bool addref) {
l_handle_event("buffer_new");
}
+/**
+ * Removes the Scintilla buffer from the current Scintilla window.
+ * @param doc The Scintilla buffer ID to remove.
+ * @see l_remove_scintilla_buffer
+ */
void remove_scintilla_buffer(sptr_t doc) {
l_remove_scintilla_buffer(doc);
SS(SCINTILLA(focused_editor), SCI_RELEASEDOCUMENT, 0, doc);
}
+/**
+ * Splits a Scintilla window into two windows separated by a GTK pane.
+ * The buffer in the original pane is also shown in the new pane.
+ * @param editor The Scintilla window to split.
+ * @param vertical Flag indicating whether to split the window vertically or
+ * horozontally.
+ * Defaults to true.
+ */
void split_window(GtkWidget *editor, bool vertical) {
g_object_ref(editor);
int first_line = SS(SCINTILLA(editor), SCI_GETFIRSTVISIBLELINE);
@@ -146,6 +216,11 @@ void split_window(GtkWidget *editor, bool vertical) {
g_object_unref(editor);
}
+/**
+ * For a given GTK pane, remove the Scintilla windows inside it recursively.
+ * @param pane The GTK pane to remove Scintilla windows from.
+ * @see remove_scintilla_window
+ */
void remove_scintilla_windows_in_pane(GtkWidget *pane) {
GtkWidget *child1 = gtk_paned_get_child1(GTK_PANED(pane));
GtkWidget *child2 = gtk_paned_get_child2(GTK_PANED(pane));
@@ -155,6 +230,14 @@ void remove_scintilla_windows_in_pane(GtkWidget *pane) {
: remove_scintilla_window(child2);
}
+/**
+ * Unsplits the pane a given Scintilla window is in and keeps that window.
+ * If the pane to discard contains other Scintilla windows, they are removed
+ * recursively.
+ * @param editor The Scintilla window to keep when unsplitting.
+ * @see remove_scintilla_windows_in_pane
+ * @see remove_scintilla_window
+ */
bool unsplit_window(GtkWidget *editor) {
GtkWidget *pane = gtk_widget_get_parent(editor);
if (!GTK_IS_PANED(pane)) return false;
@@ -180,12 +263,27 @@ bool unsplit_window(GtkWidget *editor) {
return true;
}
+/**
+ * Resizes a GTK pane.
+ * @param editor The Scintilla window (typically the current one) contained in
+ * the GTK pane to resize.
+ * @param pos The position to resize to.
+ * @param increment Flag indicating whether or not the resizing is incremental.
+ * If true, pos is added to the current pane position; otherwise the position
+ * is absolute.
+ * Defaults to true.
+ */
void resize_split(GtkWidget *editor, int pos, bool increment) {
GtkWidget *pane = gtk_widget_get_parent(editor);
int width = gtk_paned_get_position(GTK_PANED(pane));
gtk_paned_set_position(GTK_PANED(pane), pos + (increment ? width : 0));
}
+/**
+ * Sets a user-defined GTK menubar and displays it.
+ * @param new_menubar The GTK menubar.
+ * @see l_ta_mt_newindex
+ */
void set_menubar(GtkWidget *new_menubar) {
GtkWidget *vbox = gtk_widget_get_parent(menubar);
gtk_container_remove(GTK_CONTAINER(vbox), menubar);
@@ -195,16 +293,29 @@ void set_menubar(GtkWidget *new_menubar) {
gtk_widget_show_all(menubar);
}
+/**
+ * Sets the notification statusbar text.
+ * @param text The text to display.
+ */
void set_statusbar_text(const char *text) {
gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 0);
gtk_statusbar_push(GTK_STATUSBAR(statusbar), 0, text);
}
+/**
+ * Sets the document status statusbar text.
+ * This is typically set via a Scintilla 'UpdateUI' notification.
+ * @param text The text to display.
+ */
void set_docstatusbar_text(const char *text) {
gtk_statusbar_pop(GTK_STATUSBAR(docstatusbar), 0);
gtk_statusbar_push(GTK_STATUSBAR(docstatusbar), 0, text);
}
+/**
+ * Toggles focus between a Scintilla window and the Lua command entry.
+ * When the entry is visible, the statusbars are temporarily hidden.
+ */
void command_toggle_focus() {
if (!GTK_WIDGET_HAS_FOCUS(command_entry)) {
gtk_widget_hide(statusbar); gtk_widget_hide(docstatusbar);
@@ -219,15 +330,23 @@ void command_toggle_focus() {
// Notifications/signals
+/**
+ * Signal for the 'enter' key being pressed in the Lua command entry.
+ * Evaluates the input text as Lua code.
+ * Generates a 'hide_completions' event.
+ */
static void c_activated(GtkWidget *widget, gpointer) {
l_handle_event("hide_completions");
l_ta_command(gtk_entry_get_text(GTK_ENTRY(widget)));
command_toggle_focus();
}
-/** Command entry key events.
- * Escape - Hide the completion buffer if it's open.
- * Tab - Show completion buffer.
+/**
+ * Signal for a keypress inside the Lua command entry.
+ * Currently handled keypresses:
+ * - Escape - Hide the completion buffer if it is open.
+ * - Tab - Show completion buffer.
+ * Generates a 'hide_completions' or 'show_completions' event as necessary.
*/
static bool c_keypress(GtkWidget *widget, GdkEventKey *event, gpointer) {
if (event->state == 0)
@@ -244,11 +363,18 @@ static bool c_keypress(GtkWidget *widget, GdkEventKey *event, gpointer) {
return false;
}
+/**
+ * Signal for a Scintilla notification.
+ */
static void t_notification(GtkWidget*, gint, gpointer lParam, gpointer) {
SCNotification *n = reinterpret_cast<SCNotification*>(lParam);
l_handle_scnnotification(n);
}
+/**
+ * Signal for a Scintilla command.
+ * Currently handles SCEN_SETFOCUS.
+ */
static void t_command(GtkWidget *editor, gint wParam, gpointer, gpointer) {
if (wParam >> 16 == SCEN_SETFOCUS) {
focused_editor = editor;
@@ -257,6 +383,11 @@ static void t_command(GtkWidget *editor, gint wParam, gpointer, gpointer) {
}
}
+/**
+ * Signal for a Scintilla keypress.
+ * Collects the modifier states as flags and calls Lua to handle the keypress.
+ * @see l_handle_keypress
+ */
static bool t_keypress(GtkWidget*, GdkEventKey *event, gpointer) {
bool shift = event->state & GDK_SHIFT_MASK;
bool control = event->state & GDK_CONTROL_MASK;
@@ -264,14 +395,19 @@ static bool t_keypress(GtkWidget*, GdkEventKey *event, gpointer) {
return l_handle_keypress(event->keyval, shift, control, alt);
}
+/**
+ * Signal for a Textadept window focus change.
+ */
static bool w_focus(GtkWidget*, GdkEventFocus*, gpointer) {
if (focused_editor && !GTK_WIDGET_HAS_FOCUS(focused_editor))
gtk_widget_grab_focus(focused_editor);
return false;
}
-/** Window key events.
- * Escape - hides the search dialog if it's open.
+/**
+ * Signal for a Textadept keypress.
+ * Currently handled keypresses:
+ * - Escape - hides the search frame if it's open.
*/
static bool w_keypress(GtkWidget*, GdkEventKey *event, gpointer) {
if (event->keyval == 0xff1b && GTK_WIDGET_VISIBLE(findbox)) {
@@ -281,6 +417,12 @@ static bool w_keypress(GtkWidget*, GdkEventKey *event, gpointer) {
} else return false;
}
+/**
+ * Signal for exiting Textadept.
+ * Closes the Lua State and releases resources.
+ * Generates a 'quit' event.
+ * @see l_close
+ */
static bool w_exit(GtkWidget*, GdkEventAny*, gpointer) {
if (!l_handle_event("quit")) return true;
l_close();