Add a string to the input space of the console - c

I don't really know how to explain this so the title is probably misleading.
I'm making a small text editor in C and I'm saving the contents of an entire file into an array of chars. Now I want to display the entire string to the user in a way that the user will be able to edit the string inside the command window by positioning the cursor/seek and then typing or deleting characters. Pressing enter or some other key would save the text to a new string and write it to the file.
Similar to what happens when you open a file in a linux text editor like nano or vi... You get that cursor which you can move around the file and make changes.
How can that be done in C? I don't need it to be like in the linux editors, simply putting the string inside the input area (as if the user typed the text) would be enough.

You must use Terminal capabilities (a.k.a Termcaps). They are special characters which can be interpreted by your terminal (e.g moving the cursor back and forth, or clearing the screen). Here's what Wikipedia says about Termcap databases :
A termcap database can describe the capabilities of hundreds of
different display terminals. This allows programs to have
character-based display output, independent of the type of terminal.
On-screen text editors such as vi and emacs are examples of programs
that may use termcap.
By using terminal capabilities, you will be able to control the way the cursor behaves in your editor, and how input characters shows up. A good example of this would be using colors for syntax highlighting.
I would suggest that you use the GNU Termcap library to build a cross-terminal application. Once you get the main principles, its usage is relatively straightforward, I used it back in the days to actually build a shell (such as bash, or sh).
Next, you might also want to look at the differences between canonical and non-canonical terminal modes. Given what kind of functionalities you are wanting to implement in your editor, you will likely want to override the way your terminal interprets some inputs.
See also :
Moving the cursor using Termcaps
Characters for Input Editing only available in canonical mode

This is done by writing certain special control characters to stdout, which can do things like set the color, move the cursor, etc. See https://en.wikipedia.org/wiki/ANSI_escape_code for more info.
However, if you want your editor to be portable, or you don't want to worry yourself with details, you may want to consider using the ncurses library (https://en.wikipedia.org/wiki/Ncurses), which editors like nano/vi use rather than doing it themselves.

Related

how print in c without jumping to end of text?

I'm very new to coding in general so please excuse any stupid things I say.
I am trying to print (in c) a rather long text using printf() but since it can't all fit on the screen it jumps to the end of the text and the beginning is not visible unless you scroll up. Is there an easy way to have it print the long text but stay at the beginning and allow the user to scroll down as they read before they put in the next command?
On Unix (including Linux and Mac), there are command line programs built in called more and less that does exactly what you describe. more is a program that simply waits for the user to press enter or space before showing the next page of output. less is slightly improved in that it allows vi editor keystrokes (such as j and k) to scroll up and down in the output.
more is also available on the Windows command line as well. You might even be able to find a version of less for Windows as well.
c:\users\selbie> your_program.exe | more
$> ./your_program | less
As to how to do this programmatically, that's a bit more difficult as it would involve measuring the console width and implementing your own scroll buffers. There might be open-source libraries that provide this functionality, but the console environment already has a solution for apps that produce long output.
Not really, though you may find a reasonable and simple solution is to print only a certain number of lines (say 30), then prompt the user to press Enter before display more lines.
You can even find out the current size of the terminal. That's platform specific; for Linux it's explained here: How to get terminal window width?
Not in a standard way, no.
Your output stream in C is just a stream of characters -- scrolling is handled by your terminal.
Depending on your terminal, it may be possible to control scrolling by outputting special characters, like ANSI escape codes. The ncurses library provides a portable way to manipulate terminals.
However, if you just want a more convenient way to look through your output (or really any command output), #selbie's answer is the best: use more or less. This will avoid any extra complexity in your program.

Using C I would like to format my output such that the output in the terminal stops once it hits the edge of the window

If you type ps aux into your terminal and make the window really small, the output of the command will not wrap and the format is still very clear.
When I use printf and output my 5 or 6 strings, sometimes the length of my output exceeds that of the terminal window and the strings wrap to the next line which totally screws up the format. How can I write my program such that the output continues to the edge of the window but no further?
I've tried searching for an answer to this question but I'm having trouble narrowing it down and thus my search results never have anything to do with it so it seems.
Thanks!
There are functions that can let you know information about the terminal window, and some others that will allow you to manipulate it. Look up the "ncurses" or the "termcap" library.
A simple approach for solving your problem will be to get the terminal window size (specially the width), and then format your output accordingly.
There are two possible answers to fix your problem.
Turn off line wrapping in your terminal emulator(if it supports it).
Look into the Curses library. Applications like top or vim use the Curses library for screen formatting.
You can find, or at least guess, the width of the terminal using methods that other answers describe. That's only part of the problem however -- the tricky bit is formatting the output to fit the console. I don't believe there's any alternative to reading the text word by word, and moving the output to the next line when a word would overflow the width. You'll need to implement a method to detect where the white-space is, allowing for the fact that there could be multiple white spaces in a row. You'll need to decide how to handle line-breaking white-space, like CR/LF, if you have any. You'll need to decide whether you can break a word on punctuation (e.g, a hyphen). My approach is to use a simple finite-state machine, where the states are "At start of line", "in a word", "in whitespace", etc., and the characters (or, rather character classes) encountered are the events that change the state.
A particular complication when working in C is that there is little-to-no built-in support for multi-byte characters. That's fine for text which you are certain will only ever be in English, and use only the ASCII punctuation symbols, but with any kind of internationalization you need to be more careful. I've found that it's easiest to convert the text into some wide format, perhaps UTF-32, and then work with arrays of 32-bit integers to represent the characters. If your text is UTF-8, there are various tricks you can use to avoid having to do this conversion, but they are a bit ugly.
I have some code I could share, but I don't claim it is production quality, or even comprehensible. This simple-seeming problem is actually far more complicated than first impressions suggest. It's easy to do badly, but difficult to do well.

Display deletable characters in a terminal (using libedit/editline or readline)

I am currently using libedit for "readline"-functionallity, so far it works really well, but I would like to display characters (spaces) after the prompt which are deleteable by the user. Similiar to IPython:
As you can see there are 4 additional characters (spaces) automatically added, which I can remove by pressing backspace, until I reach the prompt ...:.
I would like to mimic this behaviour with libedit/editline and if there is no way to do this (e.g. using curses or the underlaying terminal function which libedit uses), I would switch to readline.
How is this possible to do, preferable with libedit/editline or readline.
Edit: I tried modifying rl_line_buffer, this didn't modify the display, only the value I get from readline.

How to implement previous-command-scroll in a standalone shell program?

For a class project we have to implement a basic Linux shell. As it stands now I have everything working to fully implement basic functionality except for the "UP" key previous command scrolling feature.
How might something like this be implemented? I realize it may be as simple as retaining an array of char* to the input strings, but how do we capture "UP" key button presses?
Once we have the above implemented, how can you write to stdout without making it permanent? That is, when you press "UP" again then it erases what was previously written with another command.
A practical way to implement the up key would be to use GNU readline library (and its history sub-library). BTW, some shells actually do use GNU readline (it is under GPL license). And you'll get line edition also. And you could implement completion with the tab key, etc.
There are other ways, like using ncurses or termcap etc... Or emitting ANSI escape codes on a raw terminal. See also the tty demystified & termios(3)...
BTW, most Linux shells are free software, so you could study their source code.
If you are using non-buffered character-by-character input directly from STDIN (which means, among other things, control characters such as CTRL+C are not handled automatically), then you will be reading byte-by-byte. Arrow keys, unlike ASCII symbols, put multiple bytes on STDIN because they are excape sequences. These bytes differ from system to system. The easiest way to determine the escape sequence on your system is to execute the cat command with no arguments, then hit the arrow keys. Something like ^[[A will be displayed, you will need to convert that sequence from ASCII to hex bytes.
Once you've done that, you can read the bytes one at a time with get_char(), just like you're probably already doing in your input function anyway.

Background c program for keyboard mapping

I have installed a Bramma TTF file in my windows 8 system. Through a windows character map, I was able to find individual character code. Attached below the screenshot of the map. We can see at the right bottom side, the character code for "!" is 0x21. Similarly, I can find all the character code of all other letters.
Now I defined a character mapping for this font with my US based keyboard layout. For example, I mapped physical character 'a' in the keyboard to the character shown in 3rd row and 1st column. [whenever I hit 'a' from the keyboard, the corresponding character has to be displayed]
I would like to write a background C program such that it listens the keyboard hit and as per my previously defined character mapping, my C program should output that mapped character. i.e., when i hit character 'a' from the keyboard it should return the mapped character.
Can any one help me out in solving this problem or else just give me a lead towards the solution.
I'm somewhat familiar with these kind of fonts, they popped up in other questions at SO. The kind of questions from users that tried to deal with the consequences of using such a font. They are rather grave.
The biggest problem is that this font is not Unicode compatible. The actual string that underlies the text that's rendered to the screen is very different, containing characters from the ANSI character set. What goes horribly wrong is when the program that displays these strings saves the data. The data file contains the original strings, a good example is an Excel spreadsheet. This spreadsheet just contains gibberish when it is read by any other program. Especially bad when read by a program on another machine that doesn't have the same font installed. Very, very painful.
You are in fact making this problem worse by even destroying the normal mapping between keyboard to ANSI character. The 1st character in the 3rd row is produced by typing a capital I (eye) on the keyboard.
The message is clear: don't do this. Windows supports Unicode compatible fonts with Indic scripts well, fonts like Sylfaen, Mangal, Latha. All of which are available on my Windows 8 machine, about ten thousand miles away from where they are normally used. It also has Indic keyboard layouts available under the Language applet, I just picked one as an example:
Well, it is your funeral. You don't have to write a C program to translate these keystrokes, you need a custom keyboard layout. It is a DLL. You normally need the DDK to build them, but there is simple tooling available to auto-generate them. It doesn't get any easier than with MKLC, the Microsoft Keyboard Layout Creator. Web page and download link are here.
Probably you should use autohotkey.
With this application, you can listen to a set of keys, & then send a different set of keys.
This can be used as implementation of "autocorrect"
e.g.
:*:btw::By the way `
will autocorrect btw to By the way.
autohotkey supports quite complicated scripts, & many scripts are already available online.
On another note, if you only want english keyboard to print malayalam unicode characters, you may also think of a popular software called baraha
Google's Virtual Keyboard (also works with your physical keyboard)
https://code.google.com/apis/ajax/playground/#virtual_keyboard
http://www.tavultesoft.com/ allows you to create keyboards for MSWindows and the web. Over 1000 keyboards are readily provided. There is a developer and a user version. With the developer version you may create installation programs which install fonts, keyboards, keymaps and documentation.

Resources