├── Autocomplete.ahk ├── README.md ├── Screenshot.png ├── Screenshot2.png └── WordList.txt /Autocomplete.ahk: -------------------------------------------------------------------------------- 1 | codepage = 65001 ; UTF-8 2 | FileEncoding, UTF-8 3 | #NoEnv 4 | 5 | #Warn All 6 | #Warn LocalSameAsGlobal, Off 7 | 8 | #MaxThreadsBuffer On 9 | 10 | SetBatchLines, -1 11 | 12 | WordListFile := A_ScriptDir . "\WordList.txt" ;path of the wordlist file 13 | SettingsFile := A_ScriptDir . "\Settings.ini" ;path of the settings file 14 | 15 | MaxResults := 20 ;maximum number of results to display 16 | OffsetX := 0 ;offset in caret position in X axis 17 | OffsetY := 20 ;offset from caret position in Y axis 18 | BoxHeight := 165 ;height of the suggestions box in pixels 19 | ShowLength := 3 ;minimum length of word before showing suggestions 20 | CorrectCase := False ;whether or not to fix uppercase or lowercase to match the suggestion 21 | 22 | NormalKeyList := "a`nb`nc`nd`ne`nf`ng`nh`ni`nj`nk`nl`nm`nn`no`np`nq`nr`ns`nt`nu`nv`nw`nx`ny`nz" ;list of key names separated by `n that make up words in upper and lower case variants 23 | NumberKeyList := "1`n2`n3`n4`n5`n6`n7`n8`n9`n0" ;list of key names separated by `n that make up words as well as their numpad equivalents 24 | OtherKeyList := "'`n-" ;list of key names separated by `n that make up words 25 | ResetKeyList := "Esc`nSpace`nHome`nPGUP`nPGDN`nEnd`nLeft`nRight`nRButton`nMButton`n,`n.`n/`n[`n]`n;`n\`n=`n```n""" ;list of key names separated by `n that cause suggestions to reset 26 | TriggerKeyList := "Tab`nEnter" ;list of key names separated by `n that trigger completion 27 | 28 | IniRead, MaxResults, %SettingsFile%, Settings, MaxResults, %MaxResults% 29 | IniRead, ShowLength, %SettingsFile%, Settings, ShowLength, %ShowLength% 30 | IniRead, CorrectCase, %SettingsFile%, Settings, CorrectCase, %CorrectCase% 31 | 32 | IniRead, NormalKeyList, %SettingsFile%, Keys, NormalKeyList, %NormalKeyList% 33 | NormalKeyList := URLDecode(NormalKeyList) 34 | IniRead, NumberKeyList, %SettingsFile%, Keys, NumberKeyList, %NumberKeyList% 35 | NumberKeyList := URLDecode(NumberKeyList) 36 | IniRead, OtherKeyList, %SettingsFile%, Keys, OtherKeyList, %OtherKeyList% 37 | OtherKeyList := URLDecode(OtherKeyList) 38 | IniRead, ResetKeyList, %SettingsFile%, Keys, ResetKeyList, %ResetKeyList% 39 | ResetKeyList := URLDecode(ResetKeyList) 40 | IniRead, TriggerKeyList, %SettingsFile%, Keys, TriggerKeyList, %TriggerKeyList% 41 | TriggerKeyList := URLDecode(TriggerKeyList) 42 | 43 | TrayTip, Settings, Click the tray icon to modify settings, 5, 1 44 | 45 | CoordMode, Caret 46 | SetKeyDelay, 0 47 | SendMode, Input 48 | 49 | ;obtain desktop size across all monitors 50 | SysGet, ScreenWidth, 78 51 | SysGet, ScreenHeight, 79 52 | 53 | FileRead, WordList, %WordListFile% 54 | PrepareWordList(WordList) 55 | 56 | ;set up tray menu 57 | Menu, Tray, NoStandard 58 | Menu, Tray, Click, 1 59 | Menu, Tray, Add, Settings, ShowSettings 60 | Menu, Tray, Add 61 | Menu, Tray, Add, Exit, ExitScript 62 | Menu, Tray, Default, Settings 63 | 64 | ;set up suggestions window 65 | Gui, Suggestions:Default 66 | Gui, Font, s10, Courier New 67 | Gui, Add, ListBox, x0 y0 h%BoxHeight% 0x100 vMatched gCompleteWord AltSubmit 68 | Gui, -Caption +ToolWindow +AlwaysOnTop +LastFound 69 | hWindow := WinExist() 70 | Gui, Show, h%BoxHeight% Hide, AutoComplete 71 | 72 | Gosub, ResetWord 73 | 74 | SetHotkeys(NormalKeyList,NumberKeyList,OtherKeyList,ResetKeyList,TriggerKeyList) 75 | 76 | OnExit, ExitSub 77 | Return 78 | 79 | ExitSub: 80 | Gui, Settings:Submit 81 | 82 | ;write settings 83 | IniWrite, % URLEncode(MaxResults), %SettingsFile%, Settings, MaxResults 84 | IniWrite, % URLEncode(ShowLength), %SettingsFile%, Settings, ShowLength 85 | IniWrite, % URLEncode(CorrectCase), %SettingsFile%, Settings, CorrectCase 86 | 87 | IniWrite, % URLEncode(NormalKeyList), %SettingsFile%, Keys, NormalKeyList 88 | IniWrite, % URLEncode(NumberKeyList), %SettingsFile%, Keys, NumberKeyList 89 | IniWrite, % URLEncode(OtherKeyList), %SettingsFile%, Keys, OtherKeyList 90 | IniWrite, % URLEncode(ResetKeyList), %SettingsFile%, Keys, ResetKeyList 91 | IniWrite, % URLEncode(TriggerKeyList), %SettingsFile%, Keys, TriggerKeyList 92 | 93 | ;write wordlist file 94 | File := FileOpen(WordListFile,"w") 95 | File.Seek(0) 96 | Length := File.Write(WordList) 97 | File.Length := Length 98 | ExitApp 99 | 100 | ExitScript: 101 | ExitApp 102 | 103 | ShowSettings: 104 | ;do not show settings window if already shown 105 | Gui, Settings:+LastFoundExist 106 | If WinExist() 107 | Return 108 | 109 | Gui, Settings:Default 110 | Gui, Font,, Arial 111 | Gui, Font,, Century Gothic 112 | Gui, Color, White, FFF8F8 113 | 114 | Gui, Font, s24 cFFAAAA 115 | Gui, Add, Text, x10 y10 w540 h45 Center, استكمال تلقائي 116 | Gui, Add, Progress, x10 y55 w540 h1 BackgroundEEDDDD, 0 117 | 118 | 119 | Gui, Font, s14 c885555 120 | 121 | Gui, Add, Text, x10 y73 w180 h30, عدد الاقتراحات 122 | Gui, Add, Edit, x190 y70 w80 h30 Left Number 123 | Gui, Add, UpDown, Range1-100 vMaxResults, %MaxResults% 124 | Gui, Add, Text, x10 y113 w180 h30, طول الدليل 125 | Gui, Add, Edit, x190 y110 w80 h30 Right Number 126 | Gui, Add, UpDown, Range1-10, %ShowLength% 127 | 128 | Gui, Add, Checkbox, x10 y150 w260 h30 Checked%CorrectCase% vCorrectCase, تصحيح الحالة 129 | 130 | Gui, Add, Edit, x10 y210 w230 h30 vNewWord 131 | Gui, Add, Button, x240 y210 w30 h30 Disabled vAddWord gAddWord, + 132 | Gui, Add, Button, x10 y250 w260 h40 Disabled vRemoveWord gRemoveWord, احذف المحددة 133 | Gui, Font, s8, Courier New 134 | Gui, Add, ListView, x290 y70 w260 h220 -Hdr vWords, Words 135 | 136 | Gui, Color, White 137 | Gui, +ToolWindow +AlwaysOnTop 138 | Gui, Show, w560 h300, Autocomplete by Uberi 139 | 140 | LV_Add("", "يحمّل قائمة الكلمات...") 141 | Sleep, 0 142 | 143 | ;populate list with entries from wordlist 144 | GuiControl, -Redraw, Words 145 | Loop, Parse, WordList, `n 146 | LV_Add("", A_LoopField) 147 | LV_Delete(1) 148 | GuiControl, +Redraw, Words 149 | 150 | GuiControl, Enable, AddWord 151 | GuiControl, Enable, RemoveWord 152 | Return 153 | 154 | SettingsGuiEscape: 155 | SettingsGuiClose: 156 | Gui, Settings:Default 157 | Gui, Submit 158 | Gui, Destroy 159 | Return 160 | 161 | AddWord: 162 | Gui, Settings:Default 163 | GuiControlGet, NewWord,, NewWord 164 | Index := LV_Add("Select Focus", NewWord) 165 | LV_Modify(Index, "Vis") 166 | WordList .= "`n" . NewWord 167 | Return 168 | 169 | RemoveWord: 170 | Gui, Settings:Default 171 | TempList := "`n" . WordList . "`n" 172 | GuiControl, -Redraw, Words 173 | While, CurrentRow := LV_GetNext() 174 | { 175 | LV_Delete(CurrentRow) 176 | Position := InStr(TempList,"`n",True,1,CurrentRow) 177 | TempList := SubStr(TempList,1,Position) . SubStr(TempList,InStr(TempList,"`n",True,Position + 1) + 1) 178 | } 179 | GuiControl, +Redraw, Words 180 | WordList := SubStr(TempList,2,-1) 181 | Return 182 | 183 | #IfWinExist AutoComplete ahk_class AutoHotkeyGUI 184 | 185 | ~LButton:: 186 | MouseGetPos,,, Temp1 187 | If (Temp1 != hWindow) 188 | Gosub, ResetWord 189 | Return 190 | 191 | Up:: 192 | Gui, Suggestions:Default 193 | GuiControlGet, Temp1,, Matched 194 | If Temp1 > 1 ;ensure value is in range 195 | GuiControl, Choose, Matched, % Temp1 - 1 196 | Return 197 | 198 | Down:: 199 | Gui, Suggestions:Default 200 | GuiControlGet, Temp1,, Matched 201 | GuiControl, Choose, Matched, % Temp1 + 1 202 | Return 203 | 204 | #IfWinExist 205 | 206 | ~BackSpace:: 207 | CurrentWord := SubStr(CurrentWord,1,-1) 208 | Gosub, Suggest 209 | Return 210 | 211 | Key: 212 | CurrentWord .= SubStr(A_ThisHotkey,2) 213 | Gosub, Suggest 214 | Return 215 | 216 | ShiftedKey: 217 | Char := SubStr(A_ThisHotkey,3) 218 | StringUpper, Char, Char 219 | CurrentWord .= Char 220 | Gosub, Suggest 221 | Return 222 | 223 | NumpadKey: 224 | CurrentWord .= SubStr(A_ThisHotkey,8) 225 | Gosub, Suggest 226 | Return 227 | 228 | ResetWord: 229 | CurrentWord := "" 230 | Gui, Suggestions:Hide 231 | Return 232 | 233 | Suggest: 234 | Gui, Suggestions:Default 235 | 236 | ;check word length against minimum length 237 | If StrLen(CurrentWord) < ShowLength -2 238 | { 239 | Gui, Hide 240 | Return 241 | } 242 | 243 | MatchList := Suggest(CurrentWord,WordList) 244 | 245 | ;check for a lack of matches 246 | If (MatchList = "") 247 | { 248 | Gui, Hide 249 | Return 250 | } 251 | 252 | ;limit the number of results 253 | Position := InStr(MatchList,"|",True,1,MaxResults) 254 | If Position 255 | MatchList := SubStr(MatchList,1,Position - 1) 256 | 257 | ;find the longest text width 258 | MaxWidth := 0 259 | Loop, Parse, MatchList, | 260 | { 261 | Width := TextWidth(A_LoopField) 262 | If (Width > MaxWidth) 263 | MaxWidth := Width 264 | } 265 | MaxWidth += 30 ;add room for the scrollbar 266 | 267 | ;update the interface 268 | GuiControl,, Matched, |%MatchList% 269 | GuiControl, Choose, Matched, 1 270 | GuiControl, Move, Matched, w%MaxWidth% ;set the control width 271 | PosX := A_CaretX + OffsetX 272 | If PosX + MaxWidth > ScreenWidth ;past right side of the screen 273 | PosX := ScreenWidth - MaxWidth 274 | PosY := A_CaretY + OffsetY 275 | If PosY + BoxHeight > ScreenHeight ;past bottom of the screen 276 | PosY := ScreenHeight - BoxHeight 277 | Gui, Show, x%PosX% y%PosY% w%MaxWidth% NoActivate ;show window 278 | Return 279 | 280 | CompleteWord: 281 | Critical 282 | 283 | ;only trigger word completion on non-interface event or double click on matched list 284 | If (A_GuiEvent != "" && A_GuiEvent != "DoubleClick") 285 | Return 286 | 287 | Gui, Suggestions:Default 288 | Gui, Hide 289 | 290 | ;retrieve the word that was selected 291 | GuiControlGet, Index,, Matched 292 | TempList := "|" . MatchList . "|" 293 | Position := InStr(TempList,"|",0,1,Index) + 1 294 | NewWord := SubStr(TempList,Position,InStr(TempList,"|",0,Position) - Position) 295 | 296 | SendWord(CurrentWord,NewWord,CorrectCase) 297 | 298 | Gosub, ResetWord 299 | Return 300 | 301 | PrepareWordList(ByRef WordList) 302 | { 303 | If InStr(WordList,"`r") 304 | StringReplace, WordList, WordList, `r,, All 305 | While, InStr(WordList,"`n`n") ;remove blank lines within the list 306 | StringReplace, WordList, WordList, `n`n, `n, All 307 | WordList := Trim(WordList,"`n") ;remove blank lines at the beginning and end 308 | } 309 | 310 | SetHotkeys(NormalKeyList,NumberKeyList,OtherKeyList,ResetKeyList,TriggerKeyList) 311 | { 312 | Loop, Parse, NormalKeyList, `n 313 | { 314 | Hotkey, ~%A_LoopField%, Key, UseErrorLevel 315 | Hotkey, ~+%A_LoopField%, ShiftedKey, UseErrorLevel 316 | } 317 | 318 | Loop, Parse, NumberKeyList, `n 319 | { 320 | Hotkey, ~%A_LoopField%, Key, UseErrorLevel 321 | Hotkey, ~Numpad%A_LoopField%, NumpadKey, UseErrorLevel 322 | } 323 | 324 | Loop, Parse, OtherKeyList, `n 325 | Hotkey, ~%A_LoopField%, Key, UseErrorLevel 326 | 327 | Loop, Parse, ResetKeyList, `n 328 | Hotkey, ~*%A_LoopField%, ResetWord, UseErrorLevel 329 | 330 | Hotkey, IfWinExist, AutoComplete ahk_class AutoHotkeyGUI 331 | Loop, Parse, TriggerKeyList, `n 332 | Hotkey, %A_LoopField%, CompleteWord, UseErrorLevel 333 | } 334 | 335 | Suggest(CurrentWord,ByRef WordList) 336 | { 337 | 338 | CurrentWord := convertArabic(CurrentWord) 339 | Pattern := RegExReplace(CurrentWord,"S).","$0.*") ;subsequence matching pattern 340 | ; MsgBox, %CurrentWord%, %Pattern% ;; for debug porpus 341 | ;treat accented characters as equivalent to their unaccented counterparts 342 | ; Pattern := RegExReplace(Pattern,"S)[a" . Chr(224) . Chr(226) . "]","[a" . Chr(224) . Chr(226) . "]") 343 | ; Pattern := RegExReplace(Pattern,"S)[c" . Chr(231) . "]","[c" . Chr(231) . "]") 344 | ; Pattern := RegExReplace(Pattern,"S)[e" . Chr(233) . Chr(232) . Chr(234) . Chr(235) . "]","[e" . Chr(233) . Chr(232) . Chr(234) . Chr(235) . "]") 345 | ; Pattern := RegExReplace(Pattern,"S)[i" . Chr(238) . Chr(239) . "]","[i" . Chr(238) . Chr(239) . "]") 346 | ; Pattern := RegExReplace(Pattern,"S)[o" . Chr(244) . "]","[o" . Chr(244) . "]") 347 | ; Pattern := RegExReplace(Pattern,"S)[u" . Chr(251) . Chr(249) . "]","[u" . Chr(251) . Chr(249) . "]") 348 | 349 | Pattern := "`nimS)^" . Pattern ;match options 350 | 351 | ;search for words matching the pattern 352 | MatchList := "" 353 | Position := 1 354 | While, Position := RegExMatch(WordList,Pattern,Word,Position) 355 | { 356 | Position += StrLen(Word) 357 | StringReplace, Word, Word, %A_Tab%, %A_Space%%A_Space%%A_Space%%A_Space%, All ;convert tabs to spaces 358 | MatchList .= Word . "`n" 359 | ; MsgBox, %Word% 360 | } 361 | MatchList := SubStr(MatchList,1,-1) ;remove trailing delimiter 362 | 363 | ;sort by score 364 | SortedMatches := "" 365 | Loop, Parse, MatchList, `n 366 | SortedMatches .= Score(CurrentWord,A_LoopField) . "`t" . A_LoopField . "`n" 367 | SortedMatches := SubStr(SortedMatches,1,-1) 368 | Sort, SortedMatches, N R ;rank results numerically descending by score 369 | 370 | ;remove scores 371 | MatchList := "" 372 | Loop, Parse, SortedMatches, `n 373 | MatchList .= SubStr(A_LoopField,InStr(A_LoopField,"`t",True,-1) + 1) . "|" 374 | 375 | Return, MatchList 376 | } 377 | 378 | Score(Word,Entry) 379 | { 380 | Score := 100 381 | 382 | Length := StrLen(Word) 383 | 384 | ;determine prefixing 385 | Position := 1 386 | While, Position <= Length && SubStr(Word,Position,1) = SubStr(Entry,Position,1) 387 | Position ++ 388 | Score *= Position ** 8 389 | 390 | ;determine number of superfluous characters 391 | RegExMatch(Entry,"`nimS)^" . SubStr(RegExReplace(Word,"S).","$0.*"),1,-2),Remaining) 392 | Score *= (1 + StrLen(Remaining) - Length) ** -1.5 393 | 394 | Return, Score 395 | } 396 | 397 | SendWord(CurrentWord,NewWord,CorrectCase = False) 398 | { 399 | If CorrectCase 400 | { 401 | Position := 1 402 | CaseSense := A_StringCaseSense 403 | StringCaseSense, Locale 404 | Loop, Parse, CurrentWord 405 | { 406 | Position := InStr(NewWord,A_LoopField,False,Position) ;find next character in the current word if only subsequence matched 407 | If A_LoopField Is Upper 408 | { 409 | Char := SubStr(NewWord,Position,1) 410 | StringUpper, Char, Char 411 | NewWord := SubStr(NewWord,1,Position - 1) . Char . SubStr(NewWord,Position + 1) 412 | } 413 | } 414 | StringCaseSense, %CaseSense% 415 | } 416 | 417 | ;send the word 418 | Send, % "{BS " . StrLen(CurrentWord) . "}" ;clear the typed word 419 | SendRaw, %NewWord% 420 | } 421 | 422 | TextWidth(String) 423 | { 424 | static Typeface := "Courier New" 425 | static Size := 10 426 | static hDC, hFont := 0, Extent 427 | If !hFont 428 | { 429 | hDC := DllCall("GetDC","UPtr",0,"UPtr") 430 | Height := -DllCall("MulDiv","Int",Size,"Int",DllCall("GetDeviceCaps","UPtr",hDC,"Int",90),"Int",72) 431 | hFont := DllCall("CreateFont","Int",Height,"Int",0,"Int",0,"Int",0,"Int",400,"UInt",False,"UInt",False,"UInt",False,"UInt",0,"UInt",0,"UInt",0,"UInt",0,"UInt",0,"Str",Typeface) 432 | hOriginalFont := DllCall("SelectObject","UPtr",hDC,"UPtr",hFont,"UPtr") 433 | VarSetCapacity(Extent,8) 434 | } 435 | DllCall("GetTextExtentPoint32","UPtr",hDC,"Str",String,"Int",StrLen(String),"UPtr",&Extent) 436 | Return, NumGet(Extent,0,"UInt") 437 | } 438 | 439 | URLEncode(Text) 440 | { 441 | StringReplace, Text, Text, `%, `%25, All 442 | FormatInteger := A_FormatInteger, FoundPos := 0 443 | SetFormat, IntegerFast, Hex 444 | While, FoundPos := RegExMatch(Text,"S)[^\w-\.~%]",Char,FoundPos + 1) 445 | StringReplace, Text, Text, %Char%, % "%" . SubStr("0" . SubStr(Asc(Char),3),-1), All 446 | SetFormat, IntegerFast, %FormatInteger% 447 | Return, Text 448 | } 449 | 450 | URLDecode(Encoded) 451 | { 452 | FoundPos := 0 453 | While, FoundPos := InStr(Encoded,"%",False,FoundPos + 1) 454 | { 455 | Value := SubStr(Encoded,FoundPos + 1,2) 456 | If (Value != "25") 457 | StringReplace, Encoded, Encoded, `%%Value%, % Chr("0x" . Value), All 458 | } 459 | StringReplace, Encoded, Encoded, `%25, `%, All 460 | Return, Encoded 461 | } 462 | 463 | convertArabic(word) 464 | { 465 | StringReplace, word, word, a, ش, All 466 | StringReplace, word, word, z, ئ, All 467 | StringReplace, word, word, e, ث, All 468 | StringReplace, word, word, r, ق, All 469 | StringReplace, word, word, t, ف, All 470 | StringReplace, word, word, y, غ, All 471 | StringReplace, word, word, u, ع, All 472 | StringReplace, word, word, i, ه, All 473 | StringReplace, word, word, o, خ, All 474 | StringReplace, word, word, p, ح, All 475 | 476 | 477 | StringReplace, word, word, s, س, All 478 | StringReplace, word, word, q, ض, All 479 | StringReplace, word, word, d, ي, All 480 | StringReplace, word, word, f, ب, All 481 | StringReplace, word, word, g, ل, All 482 | StringReplace, word, word, h, ا, All 483 | StringReplace, word, word, j, ت, All 484 | StringReplace, word, word, k, ن, All 485 | StringReplace, word, word, l, ن, All 486 | 487 | StringReplace, word, word, w, ص, All 488 | StringReplace, word, word, x, ء, All 489 | StringReplace, word, word, c, ؤ, All 490 | StringReplace, word, word, v, ر, All 491 | StringReplace, word, word, b, لا, All 492 | StringReplace, word, word, n, ى, All 493 | 494 | 495 | return word 496 | } 497 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | تعريب برنامج الاستكمال التلقائي "Autocomplete by Uberi" 2 | ===================== 3 | يقوم التطبيق باقتراح واستكمال الكلمات لدى كتابتها، ما يسمح بالكتابة بشكل أفضل وأسرع 4 | # [احصل عليه الآن](https://github.com/linuxscout/Autocomplete) 5 | 6 | ![Screenshot](Screenshot.png) 7 | 8 | طريقة الاستخدام 9 | ----- 10 | 11 | 1. قم بفك ضغط الملف المُحمّل 12 | 2. في حال ما إذا قُمت بتحميل التطبيق الجاهز، قم بفتح `Autocomplete.exe` 13 | 3. أما لو قمت بتحميل الشفرة المصدرية، فتحقق أولا بأنك تملك أحدث إصدار من تطبيق [AutoHotkey](http://www.autohotkey.com/) ومن ثم قم بتشغيل `Autocomplete.ahk`. 14 | 4. اشرع في الكتابة في أي مكان وستظهر لك علبة الاقتراحات بعد بضعة حروف. 15 | 5. استعن بزري التوجيه `فوق` و `تحت` لاختيار اقتراح آخر إذا كان الاقتراح الحالي غير مُناسب. 16 | 6. اضغط على زر `Enter` أو `Tab` لتأكيد الاختيار. 17 | 18 | إعدادات مُتقدّمة 19 | -------- 20 | انقر على زر التطبيق (بجانب ساعة النظام) لتظهر لك لوحة التحكم في إعدادات التطبيق التي تسمح لك بالتحكم مثلًا في عدد الاقتراحات التي تظهر في كل مرة أو في عدد الحروف الواجب كتابتها قبل ظهور الاقتراحات. 21 | 22 | سيكون بإمكانك أيضا التحكم في قائمة الكلمات بالإضافة أو بالحذف. سيتم حفظ جميع الإعدادات لدى إغلاق التطبيق بشكل آلي. 23 | 24 | يتم حفظ قائمة الكلمات في ملف `WordList.txt`، حيث يتم تخصيص سطر لكل كلمة. لن تحتاج سوى إلى مُحرر نصوص لتحرير هذا الملف، لكنك ستحتاج إلى مُحرر نصوص يتحمل فتح الملفات الكبيرة لأنه من المُحتمل أن تنهار المُحررات التي لا تدعم ذلك. 25 | 26 | أما الإعدادات فهي محفوظة في ملف `Settings.ini` الموجود داخل مُجلد التطبيق. يحتوي هذا الملف على إعدادات إضافية لا تظهر في لوحة التحكم آنفة الذكر خاصة تلك التي تتعلق بإعدادات المفاتيح. 27 | 28 | إعدادات المفاتيح عبارة عن قائمة عناوين مُرمّزة لأسماء المفاتيح، مثل `Space` أو `d` ويتم الفصل ما بين كل مفتاحين بسطر جديد (العنوان المُرمّز للسطر الجديد هو `%0A`). بإمكانك التعديل عليها وفق المفاتيح التي يقبلها التطبيق. 29 | 30 | الترخيص 31 | ------- 32 | 33 | This program is provided under the 3-clause BSD license. In short, this gives you the right to modify and distribute the program as you please, as long as you make sure the notice below is accessible to the user. 34 | 35 | Copyright (c) 2013, Anthony Zhang 36 | All rights reserved. 37 | 38 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 39 | 40 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 41 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 42 | Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 43 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 | -------------------------------------------------------------------------------- /Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxscout/Autocomplete/193fbc316b03b0a5b37a4b3dcc01fb98a2e7e94d/Screenshot.png -------------------------------------------------------------------------------- /Screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxscout/Autocomplete/193fbc316b03b0a5b37a4b3dcc01fb98a2e7e94d/Screenshot2.png --------------------------------------------------------------------------------