Jump to content

How to customize the keyboard layout on LineageOS 18.1?


Recommended Posts

If you're willing to spend a few bucks, another build option is to use AWS or a similar cloud instance.    It's been a while since I've done it, but in the past I used a super grunty EC2 and built Lineage in under 2 hours.  Good to do as a once off, but maybe not so much for frequent builds, especially if it's incremental.

Edited by Noob
  • Like 1
Link to post
Share on other sites
  • Replies 294
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

tdm added a feature to his keyboard driver that allows the user to specify a custom keyboard map. Unfortunately there is no documentation (other than the source code), but you should be able to remap

I have made a lot of keyboard-related changes on the code, now I will try to summarize them. Also, I have tried to reach a state what probably all of us may find useful and also original working

Yes, this is a 2-in-1 problem. The first one is the different keymap of shifted (QWERTY) and normal (QWERTZ) variants of keyboards we have. It is a bit strange that F(x)tec itself has generated

Posted Images

  On 8/26/2021 at 1:30 PM, VaZso said:

I would need to add special characters where "í" does not even reachable [...]

Expand  

You are probably determined to do it your way, which is fine.

However, did you even consider to just use the provided QWERTZ layout as it is? All the special characters in your example sentence can be typed using the standard layout in LOS 16.0.

"ö" is available as a key of its own. "í", "é", and "á" can be typed using the dead-key function of "´" (i.e. "´" followed by "i", "e", or "a").

Just sayin' ...

Typing french is indeed more complicated, as only "´" and "ˋ" have a dead-key function (on LOS 16, that is), not "^", which is a pity ...

  • Like 1
  • Thanks 1
Link to post
Share on other sites
  On 8/26/2021 at 3:18 PM, claude0001 said:

Typing french is indeed more complicated, as only "´" and "ˋ" have a dead-key function (on LOS 16, that is), not "^", which is a pity ...

Expand  

There is one on QWERTY. No self respecting French is using QWERTZ 🤣

Edited by Slion
  • Like 1
  • Haha 1
Link to post
Share on other sites
  On 8/26/2021 at 4:28 PM, Slion said:

There is one on QWERTY. No self respecting French is using QWERTZ 🤣

Expand  

Peuh you know what I do ?

I use only QWERTY and never ever type accents, anywhere (pc, phone, work, family). You d be surprised how tolerant people are of 0 accent writing in French.

Fuck AZERTY. Burn AZERTY. Add accents to QWERTY 😄

  • Haha 3
Link to post
Share on other sites

@VaZso To come back to my questions it seems your answers are as follow:

Which hardware keyboard do you have? Qwertz

Which keymap are you trying to use? Qwertz

Which layout do you want to use? English US

Which languages do you want to type in? Hungarian

Your configuration is convoluted because you are trying to use the qwertz keymap together with a qwerty layout.
For some keys the keymap makes the assumption that you are using the matching layout notably when the Fn key is issuing logical modifiers when associated with another key.

My advise for the time being is similar to what @claude0001 suggested. Don't try fighting the standards try using the Hungarian layout that it provided by Android I reckon your "í" should be done using Sym+I or Sym+J.

From there I suggested you could take the KCM for Hungarian and try improve it as you see fit in ways that are compatible with our driver. You could also define a custom keymap as explained at the beginning of that thread by @Sean McCreary, basically if you want to change the functions of Fn you need to define a custom keymap. However AFAICT there is a bug ATM and custom keymap do not work as they should, still it is possible to change it somehow by overwriting the driver file directly. Either way for custom keymap you will need root access as provided by Magisk.

I know it is frustrating that Fn cannot be overridden from KCM but it seems that's how it is for now. Maybe we can improve on that later. I don't want to rush into greater changes when I have not even started using Lineage OS as my daily driver. I'm also somewhat reluctant to do driver changes involving QWERTZ as it is hard from me to test and validate them cause I don't have a QWERTZ hardware and I'm not a QWERTZ user.

What ever solution you choose to settle for for now, know that it could still be improved upon in the future.

Link to post
Share on other sites
  On 8/26/2021 at 4:49 PM, Pierre said:

Fuck AZERTY. Burn AZERTY. Add accents to QWERTY

Expand  

Though I used it for years, old AZERTY really sucks. However I'm a big fan of the new AZERTY standards and have converted most of my keyboards. They are so convenient for international French like myself you can easily type in most every European language without having to look up ASCII codes 😁 Shame that nobody seems interested in adopting the new standards. French people are creature of habits and do get stuck in their old ways even though they don't make sense… so it seems 🤣

Edited by Slion
  • Haha 1
Link to post
Share on other sites
  On 8/26/2021 at 1:20 PM, Hook said:
  On 8/26/2021 at 12:40 PM, Slion said:

Does anyone knows why alt does not bring up the emoji keyboard on LOS like it did on stock?

Expand  

Using English(US) layout, it does (except with software that takes over the keyboard like Softmaker Office).

Expand  

This is strange; last time I tried, I could bring up the emoji selector by long-pressing alt on LOS 18.1, but right now I can't, no matter in which app.  This is QWERTY with English (US) International keymap.

  • Like 1
Link to post
Share on other sites
  On 8/26/2021 at 8:21 PM, Rob. S. said:

This is strange; last time I tried, I could bring up the emoji selector by long-pressing alt on LOS 18.1, but right now I can't, no matter in which app.  This is QWERTY with English (US) International keymap.

Expand  

I switched my keyboard to US International and it seems to work for me.

  • Like 1
Link to post
Share on other sites
  On 8/26/2021 at 8:28 PM, Hook said:

I switched my keyboard to US International and it seems to work for me.

Expand  

I wonder if it depends on your virtual keyboard app. Right now I could get it to show up with the default keyboard. I'm pretty sure earlier it did not work with AnySoftKeyboad.

Edited by Slion
Link to post
Share on other sites

Did you guy ever get stuck in a mode where capslock is inverted? Like when capslock is on you get lowercase and when it is off you get uppercase. I'm testing my modified driver but I'm pretty sure I did not do break that as I did not touch handling of shifts or caps.

Link to post
Share on other sites

 

  On 8/26/2021 at 3:18 PM, claude0001 said:

However, did you even consider to just use the provided QWERTZ layout as it is? All the special characters in your example sentence can be typed using the standard layout in LOS 16.0.

Expand  

On stock keyboard, I can't see á/Á, ő/Ő, ú/Ú, é/É, í/Í, ó/Ó, ű/Ű and sorry, it seems ű/Ű may be the unreachable character and not í/Í - so if I would use only characters written on Pro1's keyboard.

  On 8/26/2021 at 3:18 PM, claude0001 said:

"ö" is available as a key of its own. "í", "é", and "á" can be typed using the dead-key function of "´" (i.e. "´" followed by "i", "e", or "a").

Expand  

Yes, that is an option but it makes use of keyboard very ineffective (at least for me).

  On 8/26/2021 at 4:49 PM, Pierre said:

You d be surprised how tolerant people are of 0 accent writing in French.

Expand  

Also people are tolerant on forums for writing without accents here, however, if I would write a business e-mail without accents, that would be a shame for me...

  On 8/26/2021 at 5:06 PM, Slion said:

Which layout do you want to use? English US

Expand  

English US complemented by Hungarian.

  On 8/26/2021 at 5:06 PM, Slion said:

From there I suggested you could take the KCM for Hungarian and try improve it as you see fit in ways that are compatible with our driver.

Expand  

As the driver is the low level, kcm (at higher level) can nothing to do if driver does not generate usable data for it.

  On 8/26/2021 at 5:06 PM, Slion said:

You could also define a custom keymap as explained at the beginning of that thread by @Sean McCreary, basically if you want to change the functions of Fn you need to define a custom keymap.

Expand  

You are right, that is an option which I forgot it was included and looking at driver code, it has an option for it to load these arrays. I have also searched for it and found @tdmwrote about it here.
It seems the function works through driver's exposed interface but if I create /persist/data/keyboard/keymap file it does not find it.

Anyway, I dig a bit inside the code (still without Android studio) and found it checks it as /data/system/keyboard/keymap
I don't know if there is something which copies it there upon boot from /persist/ directory, currently I run a search for it.

  On 8/26/2021 at 5:06 PM, Slion said:

However AFAICT there is a bug ATM and custom keymap do not work as they should, still it is possible to change it somehow by overwriting the driver file directly.

Expand  

Hmm, okay, so it seems it may not copy to that partition.
As in .java file, it searches it in /data/system/keyboard directory, it may be the reason.
I don't know if it may not have read access to /persist directory or what is the reason it refers to this directory, but as it reaches qwerty/qwertz settings in /persist, it may only need a simple modification to work on /persist/data/keyboard/keymap instead.

There is a file here: lineage/device/fxtec/pro1/devicesettings/src/org/lineageos/settings/device/Constants.java
This file has the following definition (there is a macro which refers to this macro):
KEYBOARD_KEYMAP_CFG_FILE = "/data/system/keyboard/keymap";

  On 8/26/2021 at 5:06 PM, Slion said:

I'm also somewhat reluctant to do driver changes involving QWERTZ as it is hard from me to test and validate them cause I don't have a QWERTZ hardware and I'm not a QWERTZ user.

Expand  

I understand it, however, basic modifications should apply for both layouts, the difference is the layout handling.

Anyway, I have my friend's Pro1 with me for a few days (maybe early next week) for testing... so I have started a build thinking I may try some modifications and also try to set up Android Studio for that (I may need to look after how to do it properly to work on Android).

I have fetched Android, I could extract binaries from my phone, started a build but failed.

Do you know what the following message mean?
Theoretically I was followed steps in WiKi and it is the most recent version, after resync, it has the same message.

  Quote

ERROR: hardware/interfaces/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1: No API file exist
###############################################################################
# ERROR: Backward incompatible change detected on AIDL API                    #
###############################################################################
Above AIDL file(s) has changed in a backward-incompatible way, e.g. removing
a method from an interface or a field from a parcelable. If a device is shipped
with this change by ignoring this message, it has a high risk of breaking later
when a module using the interface is updated, e.g., Maineline modules.

 

Expand  

What do you think what may I do wrong?

Link to post
Share on other sites
  On 8/26/2021 at 9:11 PM, Slion said:

Did you guy ever get stuck in a mode where capslock is inverted?

Expand  

I had this problem also on stock when Android did a soft restart and somehow caps lock was toggled before it (I think in closed state). That was during my software reboot-loop I think when kernel was still counting up but Android has restarted on top.

So I don't think even if the keyboard driver is the reason.

Edited by VaZso
  • Confused 1
Link to post
Share on other sites

Interesting... if I also creates /data/system/keyboard/keymap file then it can be enabled in settings but it still does not take effect... still something needs to be checked.

It takes effect if I manually pass the whole file to /sys/bus/i2c/drivers/aw9523b/6-0058/keymap

  • Haha 1
Link to post
Share on other sites
  On 8/26/2021 at 9:36 PM, VaZso said:

Interesting... if I also creates /data/system/keyboard/keymap file then it can be enabled in settings but it still does not take effect... still something needs to be checked.

It takes effect if I manually pass the whole file to /sys/bus/i2c/drivers/aw9523b/6-0058/keymap

Expand  

That's what I was telling you earlier. That's the bug. I came to that same conclusion further up this thread.

Edited by Slion
Link to post
Share on other sites
  On 8/26/2021 at 5:42 PM, Slion said:

@Sean McCreary I've created a kernel pull request though I'm pretty sure that's not supposed to be happening on github but somewhere in Lineage gerrit. I have to take a look at the contribution process:

https://github.com/LineageOS/android_kernel_fxtec_msm8998/pull/1

Expand  

Although the CPU is fast, generally it is better to keep the code simple.

By calling a function, it needs stack handling and some amount of user memory handling, so calling a function several times in a row at driver level may not be advised.

So by using need_forced_modifier() and modifier_forced() may be readable better, performance-wise it is better as it was - at this level a bit larger code may be better if it runs faster.
I don't know if compiler optimizes it out or not however.

  • Haha 1
Link to post
Share on other sites
  On 8/26/2021 at 10:25 PM, VaZso said:

Although the CPU is fast, generally it is better to keep the code simple.

By calling a function, it needs stack handling and some amount of user memory handling, so calling a function several times in a row at driver level may not be advised.

So by using need_forced_modifier() and modifier_forced() may be readable better, performance-wise it is better as it was - at this level a bit larger code may be better if it runs faster.
I don't know if compiler optimizes it out or not however.

Expand  

I understand your concerns but:

1. Those functions are marked inline if the compiler does its job there will be no actual function call.

2. Even if they are not inlined there well be absolutely no impact whatsoever. It's not like they are being called 1000 times a second. Even that would not be a problem though.

Thanks for the code review though, I appreciate the effort.

Edited by Slion
Link to post
Share on other sites
  On 8/26/2021 at 10:54 PM, Slion said:

1. Those functions are marked inline if the compiler does its job there will be no actual function call.

Expand  

Okay, it has an inline specifier.

Anyway, I don't know why it complains me about AIDL CHECK API / "No API file exist"
Maybe it has something to do with my host system. :S

  • Like 1
Link to post
Share on other sites
  On 8/26/2021 at 11:00 PM, VaZso said:

Anyway, I don't know why it complains me about AIDL CHECK API / "No API file exist"
Maybe it has something to do with my host system. :S

Expand  

Does that break your build? If not I would not worry about it.

Edited by Slion
Link to post
Share on other sites
  On 8/26/2021 at 11:02 PM, Slion said:

Does that break you build? If not I would not worry about it.

Expand  

I suspect it was what broke my build but a lot of row followed it where I could not find errors, but then...

 LD      drivers/staging/built-in.o
  LD      drivers/built-in.o
  LINK    vmlinux
  LD      vmlinux.o
  MODPOST vmlinux.o
  GEN     .version
  CHK     include/generated/compile.h
  UPD     include/generated/compile.h
  CC      init/version.o
  LD      init/built-in.o
  KSYM    .tmp_kallsyms1.o
  KSYM    .tmp_kallsyms2.o
  LD      vmlinux
  SORTEX  vmlinux
  SYSMAP  System.map
  OBJCOPY arch/arm64/boot/Image
  DTC     arch/arm64/boot/dts/qcom/msm8998-v2-qrd-skuk-t5.dtb
  GZIP    arch/arm64/boot/Image.gz
  CAT     arch/arm64/boot/Image.gz-dtb
make[1]: Leaving directory '/root/android/lineage/out/target/product/pro1/obj/KERNEL_OBJ'
make: Leaving directory '/root/android/lineage/kernel/fxtec/msm8998'
Building DTBs
make: Entering directory '/root/android/lineage/kernel/fxtec/msm8998'
make[1]: Entering directory '/root/android/lineage/out/target/product/pro1/obj/KERNEL_OBJ'
  CHK     include/config/kernel.release
  GEN     ./Makefile
  CHK     include/generated/uapi/linux/version.h
  Using /root/android/lineage/kernel/fxtec/msm8998 as source for kernel
  CHK     include/generated/utsrelease.h
  CHK     scripts/mod/devicetable-offsets.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/bounds.h
  CHK     include/generated/asm-offsets.h
  CALL    /root/android/lineage/kernel/fxtec/msm8998/scripts/checksyscalls.sh
make[2]: 'include/generated/vdso-offsets.h' is up to date.
make[2]: 'include/generated/vdso32-offsets.h' is up to date.
  DTC     arch/arm64/boot/dts/qcom/msm8998-v2-qrd-skuk-t5.dtb
  DTC     arch/arm64/boot/dts/qcom/msm8998-v2-qrd-skuk-t5-overlay.dtbo
  VERIFY  arch/arm64/boot/dts/qcom/msm8998-v2-qrd-skuk-t5-overlay.dtbo
ufdt_apply_overlay: took 0.243323000 secs
make[1]: Leaving directory '/root/android/lineage/out/target/product/pro1/obj/KERNEL_OBJ'
make: Leaving directory '/root/android/lineage/kernel/fxtec/msm8998'
15:22:38 ninja failed with: exit status 1
ninja: build stopped: subcommand failed.

#### failed to build some targets (01:19:43 (hh:mm:ss)) ####


real    79m44.550s
user    572m13.108s
sys     32m6.487s

I don't know what subcommand it refers.

If I run brunch pro1 again:

[  0% 4/67774] AIDL CHECK API: hardware/interfaces/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current against hardware/interfaces/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1
FAILED: out/soong/.intermediates/hardware/interfaces/automotive/occupant_awareness/aidl/android.hardware.automotive.occupant_awareness-api/checkapi_current.timestamp
(out/soong/host/linux-x86/bin/aidl --stability vintf --checkapi hardware/interfaces/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1 hardware/interfaces/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current && touch out/soong/.intermediates/hardware/interfaces/automotive/occupant_awareness/aidl/android.hardware.automotive.occupant_awareness-api/checkapi_current.timestamp) || (cat system/tools/aidl/build/message_check_compatibility.txt && exit 1)
ERROR: hardware/interfaces/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/1: No API file exist
###############################################################################
# ERROR: Backward incompatible change detected on AIDL API                    #
###############################################################################
Above AIDL file(s) has changed in a backward-incompatible way, e.g. removing
a method from an interface or a field from a parcelable. If a device is shipped
with this change by ignoring this message, it has a high risk of breaking later
when a module using the interface is updated, e.g., Maineline modules.
[  0% 5/67774] AIDL CHECK API: hardware/interfaces/common/aidl/aidl_api/android.hardware.common/current against hardware/interfaces/common/aidl/aidl_api/android.hardware.common/1
FAILED: out/soong/.intermediates/hardware/interfaces/common/aidl/android.hardware.common-api/checkapi_current.timestamp
(out/soong/host/linux-x86/bin/aidl --stability vintf --checkapi hardware/interfaces/common/aidl/aidl_api/android.hardware.common/1 hardware/interfaces/common/aidl/aidl_api/android.hardware.common/current && touch out/soong/.intermediates/hardware/interfaces/common/aidl/android.hardware.common-api/checkapi_current.timestamp) || (cat system/tools/aidl/build/message_check_compatibility.txt && exit 1)
ERROR: hardware/interfaces/common/aidl/aidl_api/android.hardware.common/1: No API file exist
###############################################################################
# ERROR: Backward incompatible change detected on AIDL API                    #
###############################################################################
Above AIDL file(s) has changed in a backward-incompatible way, e.g. removing
a method from an interface or a field from a parcelable. If a device is shipped
with this change by ignoring this message, it has a high risk of breaking later
when a module using the interface is updated, e.g., Maineline modules.
[  0% 6/67774] AIDL CHECK API: hardware/interfaces/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current against hardware/interfaces/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1
FAILED: out/soong/.intermediates/hardware/interfaces/graphics/common/aidl/android.hardware.graphics.common-api/checkapi_current.timestamp
(out/soong/host/linux-x86/bin/aidl --stability vintf --checkapi hardware/interfaces/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1 hardware/interfaces/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current && touch out/soong/.intermediates/hardware/interfaces/graphics/common/aidl/android.hardware.graphics.common-api/checkapi_current.timestamp) || (cat system/tools/aidl/build/message_check_compatibility.txt && exit 1)
ERROR: hardware/interfaces/graphics/common/aidl/aidl_api/android.hardware.graphics.common/1: No API file exist
###############################################################################
# ERROR: Backward incompatible change detected on AIDL API                    #
###############################################################################
Above AIDL file(s) has changed in a backward-incompatible way, e.g. removing
a method from an interface or a field from a parcelable. If a device is shipped
with this change by ignoring this message, it has a high risk of breaking later
when a module using the interface is updated, e.g., Maineline modules.
[  0% 8/67774] AIDL CHECK API: hardware/interfaces/identity/aidl/aidl_api/android.hardware.identity/2 against hardware/interfaces/identity/aidl/aidl_api/android.hardware.identity/1
FAILED: out/soong/.intermediates/hardware/interfaces/identity/aidl/android.hardware.identity-api/checkapi_2.timestamp
(out/soong/host/linux-x86/bin/aidl --stability vintf --checkapi hardware/interfaces/identity/aidl/aidl_api/android.hardware.identity/1 hardware/interfaces/identity/aidl/aidl_api/android.hardware.identity/2 && touch out/soong/.intermediates/hardware/interfaces/identity/aidl/android.hardware.identity-api/checkapi_2.timestamp) || (cat system/tools/aidl/build/message_check_compatibility.txt && exit 1)
ERROR: hardware/interfaces/identity/aidl/aidl_api/android.hardware.identity/1: No API file exist
###############################################################################
# ERROR: Backward incompatible change detected on AIDL API                    #
###############################################################################
Above AIDL file(s) has changed in a backward-incompatible way, e.g. removing
a method from an interface or a field from a parcelable. If a device is shipped
with this change by ignoring this message, it has a high risk of breaking later
when a module using the interface is updated, e.g., Maineline modules.
[  0% 9/67774] AIDL CHECK API: hardware/interfaces/identity/aidl/aidl_api/android.hardware.identity/current against hardware/interfaces/identity/aidl/aidl_api/android.hardware.identity/2
FAILED: out/soong/.intermediates/hardware/interfaces/identity/aidl/android.hardware.identity-api/checkapi_current.timestamp
(out/soong/host/linux-x86/bin/aidl --stability vintf --checkapi hardware/interfaces/identity/aidl/aidl_api/android.hardware.identity/2 hardware/interfaces/identity/aidl/aidl_api/android.hardware.identity/current && touch out/soong/.intermediates/hardware/interfaces/identity/aidl/android.hardware.identity-api/checkapi_current.timestamp) || (cat system/tools/aidl/build/message_check_compatibility.txt && exit 1)
ERROR: hardware/interfaces/identity/aidl/aidl_api/android.hardware.identity/2: No API file exist
###############################################################################
# ERROR: Backward incompatible change detected on AIDL API                    #
###############################################################################
Above AIDL file(s) has changed in a backward-incompatible way, e.g. removing
a method from an interface or a field from a parcelable. If a device is shipped
with this change by ignoring this message, it has a high risk of breaking later
when a module using the interface is updated, e.g., Maineline modules.
[  0% 13/67774] Building Kernel Config
make: Entering directory '/root/android/lineage/kernel/fxtec/msm8998'
make[1]: Entering directory '/root/android/lineage/out/target/product/pro1/obj/KERNEL_OBJ'
  GEN     ./Makefile
#
# configuration written to .config
#
make[1]: Leaving directory '/root/android/lineage/out/target/product/pro1/obj/KERNEL_OBJ'
make: Leaving directory '/root/android/lineage/kernel/fxtec/msm8998'
make: Entering directory '/root/android/lineage/kernel/fxtec/msm8998'
make[1]: Entering directory '/root/android/lineage/out/target/product/pro1/obj/KERNEL_OBJ'
  GEN     ./Makefile
scripts/kconfig/conf  --savedefconfig=defconfig Kconfig
make[1]: Leaving directory '/root/android/lineage/out/target/product/pro1/obj/KERNEL_OBJ'
make: Leaving directory '/root/android/lineage/kernel/fxtec/msm8998'
23:15:19 ninja failed with: exit status 1

#### failed to build some targets (5 seconds) ####

 

Link to post
Share on other sites

I feel a bit better as I have created a keymap file which I can load through kernel driver, however, I had to rewrite .kcm file to use AltGr instead of fn and also use AltGr in keymap file because keyboard driver currently does not support passing "FN" as function key.

However, my custom layout works that way.

It is still not a final solution as somehow it does not load it upon boot (I have to run it manually) and a rootless solution would be much better.

Anyway, I have looked into the code and adding some options to advanced keyboard settings or adding physical layouts are seem to be really simple and straightforward.

...just I need to go through this build process on my own machine (find out what's wrong) and I can even test it if I can solve it till the end of this weekend.

  • Like 1
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

Terms