EditLib — Text Edit Control Library

Complete functionality for creating and managing single-line text input controls in Plan9Basic. Features include placeholder text, password masking, character filtering, text selection, clipboard operations, mobile keyboard types, and a rich event system. 133 functions.

CategoryCountDescription
Error Handling4edit_error, edit_errormsg$, edit_strerror$, edit_clearerror
Creation & Destruction4edit# (3 overloads), edit_free
Text Content7text, prompt, maxlength, textlength (get/set)
Password & Read-Only4password, readonly (get/set)
Font Properties14fontfamily, fontsize, fontcolor, bold, italic, underline, strikeout (get/set)
Text Alignment2textalign (get/set)
Selection7selstart, sellength, seltext$, selectall#, clearselection#
Caret Control4caretposition (get/set), gotoend#, gotobegin#
Clipboard4copy#, cut#, paste#, clear#
Mobile Features8keyboardtype, returnkeytype, checkspelling, filterchar (get/set)
Position & Size14x, y, width, height (get/set), bounds#, move#, size#
Alignment & Margins8align (get/set), margin#, margins#, marginleft/margintop (get/set)
Visibility & State6visible, enabled, opacity (get/set)
Focus5isfocused, setfocus#, resetfocus#, taborder (get/set)
Tag & Parent6tag (get/set), parent# (get/set), bringtofront#, sendtoback#
Events3616 event types × set/get + clearcallbacks#

Cross-Platform Support

PlatformStatusNotes
Windows✅ Full SupportWin32/Win64
Linux✅ Full SupportGTK-based
Android✅ Full SupportMobile keyboard types, spell check
ⓘ Note: Mobile-specific features (edit_keyboardtype#, edit_returnkeytype#, edit_checkspelling#) are designed for Android and iOS. On desktop platforms they are accepted but may have no visible effect.

Error Handling

FunctionSignatureDescription
edit_error()edit_error@Last error code (0 = no error)
edit_errormsg$()edit_errormsg$@Last error message as string
edit_strerror$(code)edit_strerror$@nDescription for a given error code
edit_clearerror()edit_clearerror@Clear the error state
╯ plan9basic
let edt# = edit#(frm#, 20, 20, 200, 30)
if edit_error() <> 0 then
    println "Error: " + edit_errormsg$()
endif

Numeric Values Reference

Plan9Basic does not have built-in constants. You can define your own named values for readability:

╯ plan9basic
' Control alignment
let ALIGN_NONE = 0
let ALIGN_TOP = 1
let ALIGN_CLIENT = 9

' Text alignment
let TEXT_LEFT = 0
let TEXT_CENTER = 1
let TEXT_RIGHT = 2

' Mobile keyboard types
let KB_DEFAULT = 0
let KB_NUMBERPAD = 2
let KB_EMAIL = 7

Control Alignment edit_align#

ValueDescription
0None (absolute positioning)
1Top
2Left
3Right
4Bottom
9Client (fill parent)

Text Alignment edit_textalign#

ValueDescription
0Left
1Center
2Right

Keyboard Types edit_keyboardtype# (Mobile)

ValueDescription
0Default
1Numbers and Punctuation
2Number Pad
3Phone Pad
7Email

Return Key Types edit_returnkeytype# (Mobile)

ValueDescription
0Default
1Done
2Go
3Next
4Search

Creation & Destruction

FunctionSignatureDescription
edit#(parent#)edit#@#Create edit with parent only (default size)
edit#(parent#, x, y, w, h)edit#@#nnnnCreate with position and size
edit#(parent#, x, y, w, h, text$)edit#@#nnnn$Create with position, size, and initial text
edit_free(edt#)edit_free@#Destroy edit control and release resources
╯ plan9basic
' Simple creation
let edt# = edit#(frm#)

' With position and size
let edt# = edit#(frm#, 20, 50, 260, 30)

' With initial text
let edt# = edit#(frm#, 20, 50, 260, 30, "Default value")

' Cleanup
edit_free(edt#)

Text Content

FunctionSignatureDescription
edit_text$(edt#)edit_text$@#Get the current text
edit_text#(edt#, text$)edit_text#@#$Set the text content
edit_prompt$(edt#)edit_prompt$@#Get placeholder / hint text
edit_prompt#(edt#, text$)edit_prompt#@#$Set placeholder text (shown when edit is empty)
edit_maxlength(edt#)edit_maxlength@#Get maximum character length (0 = unlimited)
edit_maxlength#(edt#, n)edit_maxlength#@#nSet maximum character length
edit_textlength(edt#)edit_textlength@#Get the current text length
╯ plan9basic
edit_prompt#(edt#, "Enter your name...")
edit_maxlength#(edt#, 50)

' Read text
let name$ = edit_text$(edt#)
println "Length: " + str$(edit_textlength(edt#))

Password & Read-Only

FunctionSignatureDescription
edit_password(edt#)edit_password@#Get password mode (0/1)
edit_password#(edt#, n)edit_password#@#nEnable password masking (characters shown as dots)
edit_readonly(edt#)edit_readonly@#Get read-only mode (0/1)
edit_readonly#(edt#, n)edit_readonly#@#nEnable read-only mode (text visible but not editable)
╯ plan9basic
' Password field
edit_password#(edtPass#, 1)
edit_prompt#(edtPass#, "Enter password...")

' Read-only display field
edit_readonly#(edtInfo#, 1)
edit_text#(edtInfo#, "This cannot be edited")

Font Properties

FunctionSignatureDescription
edit_fontfamily$(edt#)edit_fontfamily$@#Get font family name
edit_fontfamily#(edt#, family$)edit_fontfamily#@#$Set font family
edit_fontsize(edt#)edit_fontsize@#Get font size
edit_fontsize#(edt#, size)edit_fontsize#@#nSet font size
edit_fontcolor$(edt#)edit_fontcolor$@#Get font color
edit_fontcolor#(edt#, color$)edit_fontcolor#@#$Set font color
edit_bold(edt#)edit_bold@#Get bold state (0/1)
edit_bold#(edt#, n)edit_bold#@#nSet bold (0/1)
edit_italic(edt#)edit_italic@#Get italic state (0/1)
edit_italic#(edt#, n)edit_italic#@#nSet italic (0/1)
edit_underline(edt#)edit_underline@#Get underline state (0/1)
edit_underline#(edt#, n)edit_underline#@#nSet underline (0/1)
edit_strikeout(edt#)edit_strikeout@#Get strikeout state (0/1)
edit_strikeout#(edt#, n)edit_strikeout#@#nSet strikeout (0/1)
╯ plan9basic
edit_fontfamily#(edt#, "Consolas")
edit_fontsize#(edt#, 14)
edit_fontcolor#(edt#, "#333333")
edit_bold#(edt#, 1)

println "Font: " + edit_fontfamily$(edt#) + " " + str$(edit_fontsize(edt#)) + "pt"

Text Alignment

FunctionSignatureDescription
edit_textalign(edt#)edit_textalign@#Get text alignment (0=left, 1=center, 2=right)
edit_textalign#(edt#, n)edit_textalign#@#nSet text alignment
╯ plan9basic
edit_textalign#(edtAmount#, 2)    ' Right-align for currency input

Selection

FunctionSignatureDescription
edit_selstart(edt#)edit_selstart@#Get selection start position (0-based)
edit_selstart#(edt#, pos)edit_selstart#@#nSet selection start position
edit_sellength(edt#)edit_sellength@#Get selection length
edit_sellength#(edt#, len)edit_sellength#@#nSet selection length
edit_seltext$(edt#)edit_seltext$@#Get the currently selected text
edit_selectall#(edt#)edit_selectall#@#Select all text
edit_clearselection#(edt#)edit_clearselection#@#Clear the current selection
╯ plan9basic
' Select all on focus
edit_selectall#(edt#)
println "Selected: " + edit_seltext$(edt#)

' Programmatic selection (characters 5-10)
edit_selstart#(edt#, 5)
edit_sellength#(edt#, 5)

Caret Control

FunctionSignatureDescription
edit_caretposition(edt#)edit_caretposition@#Get caret (cursor) position
edit_caretposition#(edt#, pos)edit_caretposition#@#nSet caret position
edit_gotoend#(edt#)edit_gotoend#@#Move caret to end of text
edit_gotobegin#(edt#)edit_gotobegin#@#Move caret to beginning of text
╯ plan9basic
' Position caret at end after setting text
edit_text#(edt#, "Hello World")
edit_gotoend#(edt#)

println "Caret at: " + str$(edit_caretposition(edt#))

Clipboard

FunctionSignatureDescription
edit_copy#(edt#)edit_copy#@#Copy selected text to clipboard
edit_cut#(edt#)edit_cut#@#Cut selected text to clipboard
edit_paste#(edt#)edit_paste#@#Paste from clipboard at caret position
edit_clear#(edt#)edit_clear#@#Delete the selected text
╯ plan9basic
' Select all and copy
edit_selectall#(edt#)
edit_copy#(edt#)

Mobile Features

FunctionSignatureDescription
edit_keyboardtype(edt#)edit_keyboardtype@#Get keyboard type
edit_keyboardtype#(edt#, n)edit_keyboardtype#@#nSet virtual keyboard type (0=default, 1=numbers+punctuation, 2=numpad, 3=phone, 7=email)
edit_returnkeytype(edt#)edit_returnkeytype@#Get return key type
edit_returnkeytype#(edt#, n)edit_returnkeytype#@#nSet return key label (0=default, 1=done, 2=go, 3=next, 4=search)
edit_checkspelling(edt#)edit_checkspelling@#Get spell checking state (0/1)
edit_checkspelling#(edt#, n)edit_checkspelling#@#nEnable/disable spell checking
edit_filterchar$(edt#)edit_filterchar$@#Get allowed character set
edit_filterchar#(edt#, chars$)edit_filterchar#@#$Set allowed characters (only these can be typed)
╯ plan9basic
' Number-only input
edit_filterchar#(edtAmount#, "0123456789.")
edit_keyboardtype#(edtAmount#, 2)   ' Number Pad

' Email field
edit_keyboardtype#(edtEmail#, 7)    ' Email keyboard
edit_returnkeytype#(edtEmail#, 3)   ' "Next" key

' Phone field
edit_filterchar#(edtPhone#, "0123456789-+()")
edit_keyboardtype#(edtPhone#, 3)    ' Phone Pad

' Disable spell check for code/IDs
edit_checkspelling#(edtCode#, 0)
ⓘ Note: On desktop platforms, edit_keyboardtype# and edit_returnkeytype# are accepted but have no visible effect. edit_filterchar# works on all platforms.

Position & Size

FunctionSignatureDescription
edit_x(edt#)edit_x@#Get X position
edit_x#(edt#, x)edit_x#@#nSet X position
edit_y(edt#)edit_y@#Get Y position
edit_y#(edt#, y)edit_y#@#nSet Y position
edit_width(edt#)edit_width@#Get width
edit_width#(edt#, w)edit_width#@#nSet width
edit_height(edt#)edit_height@#Get height
edit_height#(edt#, h)edit_height#@#nSet height
edit_bounds#(edt#, x, y, w, h)edit_bounds#@#nnnnSet position and size in one call
edit_move#(edt#, x, y)edit_move#@#nnSet position only
edit_size#(edt#, w, h)edit_size#@#nnSet size only
╯ plan9basic
edit_bounds#(edt#, 20, 50, 260, 30)

' Or separately
edit_move#(edt#, 20, 50)
edit_size#(edt#, 260, 30)

Alignment & Margins

When edit_align# is set to a value other than 0, the edit control is automatically positioned by its parent container. Margins control spacing when alignment is active.

FunctionSignatureDescription
edit_align(edt#)edit_align@#Get control alignment mode
edit_align#(edt#, n)edit_align#@#nSet control alignment (0=none, 1=top, 2=left, 3=right, 4=bottom, 9=client)
edit_margin#(edt#, n)edit_margin#@#nSet uniform margin on all four sides
edit_margins#(edt#, l, t, r, b)edit_margins#@#nnnnSet individual margins (left, top, right, bottom)
edit_marginleft(edt#)edit_marginleft@#Get left margin
edit_marginleft#(edt#, n)edit_marginleft#@#nSet left margin
edit_margintop(edt#)edit_margintop@#Get top margin
edit_margintop#(edt#, n)edit_margintop#@#nSet top margin
╯ plan9basic
' Dock edit to the top of a panel with spacing
edit_align#(edt#, 1)        ' Align top
edit_margin#(edt#, 5)       ' 5px spacing all sides

' Individual margins
edit_margins#(edt#, 10, 5, 10, 5)
ⓘ Note: EditLib provides individual getters only for marginleft and margintop. Use edit_margins# to set all four sides at once.

Visibility & State

FunctionSignatureDescription
edit_visible(edt#)edit_visible@#Get visibility (0/1)
edit_visible#(edt#, n)edit_visible#@#nSet visibility (0=hidden, 1=visible)
edit_enabled(edt#)edit_enabled@#Get enabled state (0/1)
edit_enabled#(edt#, n)edit_enabled#@#nSet enabled state (0=disabled/grayed, 1=enabled)
edit_opacity(edt#)edit_opacity@#Get opacity (0.0–1.0)
edit_opacity#(edt#, value)edit_opacity#@#nSet opacity (0.0=transparent, 1.0=opaque)
╯ plan9basic
' Disable during processing
edit_enabled#(edt#, 0)
edit_opacity#(edt#, 0.5)
' ... do work ...
edit_enabled#(edt#, 1)
edit_opacity#(edt#, 1.0)

Focus

FunctionSignatureDescription
edit_isfocused(edt#)edit_isfocused@#Is this edit control focused? (0/1)
edit_setfocus#(edt#)edit_setfocus#@#Give keyboard focus to this edit
edit_resetfocus#(edt#)edit_resetfocus#@#Release focus from this edit
edit_taborder(edt#)edit_taborder@#Get tab order index
edit_taborder#(edt#, n)edit_taborder#@#nSet tab order index
╯ plan9basic
' Set logical tab order for a form
edit_taborder#(edtName#, 1)
edit_taborder#(edtEmail#, 2)
edit_taborder#(edtPhone#, 3)

' Give initial focus
edit_setfocus#(edtName#)

Tag & Parent

FunctionSignatureDescription
edit_tag(edt#)edit_tag@#Get user-defined integer tag
edit_tag#(edt#, n)edit_tag#@#nSet user-defined integer tag
edit_parent#(edt#)edit_parent#@#Get parent control pointer
edit_parent#(edt#, parent#)edit_parent#@##Move edit to a different parent
edit_bringtofront#(edt#)edit_bringtofront#@#Bring to front of Z-order
edit_sendtoback#(edt#)edit_sendtoback#@#Send to back of Z-order
╯ plan9basic
' Use tags to identify edits in shared callbacks
edit_tag#(edtName#, 1)
edit_tag#(edtEmail#, 2)

function OnChange(sender#) local tag
    tag = edit_tag(sender#)
    if tag = 1 then println "Name changed: " + edit_text$(sender#)
    elseif tag = 2 then println "Email changed: " + edit_text$(sender#)
    endif
endfunction

Events

Each event has a setter (edit_onXXX#(edt#, func$)) and a getter (edit_onXXX$(edt#)) to assign or read the callback name. Use edit_clearcallbacks#(edt#) to disconnect all callbacks at once.

Text Events

Event SetterGetterCallback SignatureWhen It Fires
edit_onchange#(edt#, func$)edit_onchange$(edt#)function name(sender#)When editing is complete (focus lost or Enter)
edit_onchangetracking#(edt#, func$)edit_onchangetracking$(edt#)function name(sender#)On every keystroke (real-time)
edit_ontyping#(edt#, func$)edit_ontyping$(edt#)function name(sender#)While the user is actively typing
ⓘ Note: OnChange vs OnChangeTracking: Use edit_onchange# for validation after editing is complete. Use edit_onchangetracking# for real-time feedback (e.g., live search). Use edit_ontyping# for typing-in-progress detection.

Focus & Input Events

Event SetterGetterCallback Signature
edit_onenter#(edt#, func$)edit_onenter$(edt#)function name(sender#)
edit_onexit#(edt#, func$)edit_onexit$(edt#)function name(sender#)
edit_onkeydown#(edt#, func$)edit_onkeydown$(edt#)function name(sender#, key, keychar$, shift$)
edit_onkeyup#(edt#, func$)edit_onkeyup$(edt#)function name(sender#, key, keychar$, shift$)
edit_onclick#(edt#, func$)edit_onclick$(edt#)function name(sender#)
edit_ondblclick#(edt#, func$)edit_ondblclick$(edt#)function name(sender#)

Mouse Events

Event SetterGetterCallback Signature
edit_onmousedown#(edt#, func$)edit_onmousedown$(edt#)function name(sender#, button, x, y, shift$)
edit_onmouseup#(edt#, func$)edit_onmouseup$(edt#)function name(sender#, button, x, y, shift$)
edit_onmousemove#(edt#, func$)edit_onmousemove$(edt#)function name(sender#, x, y, shift$)
edit_onmouseenter#(edt#, func$)edit_onmouseenter$(edt#)function name(sender#)
edit_onmouseleave#(edt#, func$)edit_onmouseleave$(edt#)function name(sender#)

Other Events

Event SetterGetterCallback Signature
edit_onresize#(edt#, func$)edit_onresize$(edt#)function name(sender#)
edit_ondragenter#(edt#, func$)edit_ondragenter$(edt#)function name(sender#)
edit_ondragover#(edt#, func$)edit_ondragover$(edt#)function name(sender#)
edit_ondragdrop#(edt#, func$)edit_ondragdrop$(edt#)function name(sender#)
edit_ondragleave#(edt#, func$)edit_ondragleave$(edt#)function name(sender#)
edit_clearcallbacks#(edt#)Disconnect all event callbacks

Complete Examples

Login Form

╯ login.bas
function OnLogin(sender#) local user$, pass$
    user$ = edit_text$(edtUser#)
    pass$ = edit_text$(edtPass#)
    println "Login: " + user$
endfunction

let frm# = form#("Login", 300, 200)
form_position#(frm#, 4)

' Username
label#(frm#, "Username:", 20, 20)
let edtUser# = edit#(frm#, 20, 45, 260, 30)
edit_prompt#(edtUser#, "Enter username...")

' Password
label#(frm#, "Password:", 20, 90)
let edtPass# = edit#(frm#, 20, 115, 260, 30)
edit_password#(edtPass#, 1)
edit_prompt#(edtPass#, "Enter password...")

' Login button
let btnLogin# = button#(frm#, "Login", 100, 160, 100, 30)
button_onclick#(btnLogin#, "OnLogin")

' Tab order
edit_taborder#(edtUser#, 1)
edit_taborder#(edtPass#, 2)
button_taborder#(btnLogin#, 3)

form_show(frm#)

while form_visible(frm#) = 1
    processmessages()
end while

Number-Only Input

╯ number_input.bas
let frm# = form#("Number Input", 300, 150)
form_position#(frm#, 4)

label#(frm#, "Enter amount:", 20, 20)
let edtAmount# = edit#(frm#, 20, 45, 200, 30)
edit_filterchar#(edtAmount#, "0123456789.")
edit_keyboardtype#(edtAmount#, 2)
edit_prompt#(edtAmount#, "0.00")
edit_textalign#(edtAmount#, 2)  ' Right-align

form_show(frm#)

while form_visible(frm#) = 1
    processmessages()
end while

Real-Time Search

╯ search.bas
function OnSearch(sender#) local txt$, len
    txt$ = edit_text$(sender#)
    len = edit_textlength(sender#)
    if len >= 3 then
        label_text#(lblResult#, "Searching for: " + txt$)
    else
        label_text#(lblResult#, "Type at least 3 characters")
    endif
endfunction

let frm# = form#("Search", 400, 200)
form_position#(frm#, 4)

let edtSearch# = edit#(frm#, 20, 20, 360, 30)
edit_prompt#(edtSearch#, "Type to search...")
edit_onchangetracking#(edtSearch#, "OnSearch")

let lblResult# = label#(frm#, "Type at least 3 characters")
label_move#(lblResult#, 20, 70)

form_show(frm#)

while form_visible(frm#) = 1
    processmessages()
end while

Keyboard Event Handler

╯ keys.bas
function OnKeyDown(sender#, key, keychar$, shift$)
    if key = 13 then
        label_text#(lblKey#, "Enter pressed!")
    elseif key = 27 then
        label_text#(lblKey#, "Escape pressed!")
    else
        label_text#(lblKey#, "Key: " + str$(key) + " Char: " + keychar$)
    endif
endfunction

let frm# = form#("Keys", 400, 200)
form_position#(frm#, 4)

let edt# = edit#(frm#, 20, 20, 360, 30)
edit_onkeydown#(edt#, "OnKeyDown")

let lblKey# = label#(frm#, "Press a key...")
label_move#(lblKey#, 20, 70)

form_show(frm#)

while form_visible(frm#) = 1
    processmessages()
end while

Contact Form

╯ contact.bas
let frm# = form#("Contact", 400, 280)
form_position#(frm#, 4)

' Name
label#(frm#, "Name:", 20, 20)
let edtName# = edit#(frm#, 20, 42, 360, 28)
edit_maxlength#(edtName#, 50)

' Email
label#(frm#, "Email:", 20, 80)
let edtEmail# = edit#(frm#, 20, 102, 360, 28)
edit_keyboardtype#(edtEmail#, 7)

' Phone
label#(frm#, "Phone:", 20, 140)
let edtPhone# = edit#(frm#, 20, 162, 360, 28)
edit_filterchar#(edtPhone#, "0123456789-+()")
edit_keyboardtype#(edtPhone#, 3)

' Submit
let btnSubmit# = button#(frm#, "Submit", 150, 220, 100, 35)

' Tab order
edit_taborder#(edtName#, 1)
edit_taborder#(edtEmail#, 2)
edit_taborder#(edtPhone#, 3)
button_taborder#(btnSubmit#, 4)

form_show(frm#)

while form_visible(frm#) = 1
    processmessages()
end while

Best Practices

PracticeWhy
Use edit_onchange# for validationFires when editing is complete, not on every keystroke
Use edit_onchangetracking# sparinglyFires on every keystroke — heavy callbacks can cause lag
Set edit_maxlength#Prevents excessive data entry
Use edit_filterchar# for restricted inputOnly allows specified characters (works on all platforms)
Set edit_keyboardtype# on mobileShows the appropriate virtual keyboard (number pad, email, phone)
Provide placeholder text with edit_prompt#Guides users on expected input format
Set edit_taborder#Enables logical keyboard Tab navigation between fields
Initialize pointer variables with Pointer#(0)Required before assigning in callbacks or conditional code

Quick Reference

FunctionSignatureDescription
edit_error / errormsg$ / strerror$ / clearerrorvariousError handling (4)
edit#(parent#[, x, y, w, h][, text$])variousCreate edit (3 overloads)
edit_free(edt#)edit_free@#Destroy edit
edit_text$ / text# / prompt$ / prompt# / maxlength / textlengthvariousText content (7)
edit_password / readonlyvariousPassword & read-only (4)
edit_fontfamily / fontsize / fontcolor / bold / italic / underline / strikeoutvariousFont properties (14)
edit_textalignedit_textalign@# / #@#nText alignment (2)
edit_selstart / sellength / seltext$ / selectall# / clearselection#variousSelection (7)
edit_caretposition / gotoend# / gotobegin#variousCaret control (4)
edit_copy# / cut# / paste# / clear#variousClipboard (4)
edit_keyboardtype / returnkeytype / checkspelling / filtercharvariousMobile features (8)
edit_x/y/width/height (get/set) / bounds# / move# / size#variousPosition & size (14)
edit_align / margin# / margins# / marginleft / margintopvariousAlignment & margins (8)
edit_visible / enabled / opacityvariousVisibility & state (6)
edit_isfocused / setfocus# / resetfocus# / tabordervariousFocus (5)
edit_tag / parent# / bringtofront# / sendtoback#variousTag & parent (6)
edit_onchange/onchangetracking/ontyping/onenter/onexit/onclick/ondblclick/onkeydown/onkeyup/onmousedown/onmouseup/onmousemove/onmouseenter/onmouseleave/onresize/ondragenter/ondragover/ondragdrop/ondragleavevariousEvents set+get (35)
edit_clearcallbacks#edit_clearcallbacks#@#Disconnect all events

133 functions. Part of the Plan9Basic GUI library system.