{"id":7440,"date":"2026-03-07T00:01:33","date_gmt":"2026-03-07T08:01:33","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=7440"},"modified":"2026-02-28T11:12:40","modified_gmt":"2026-02-28T19:12:40","slug":"the-final-task-for-mousing-around","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=7440","title":{"rendered":"The Final Task for Mousing Around"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-300x167.jpg\" alt=\"\" width=\"300\" height=\"167\" class=\"alignnone size-medium wp-image-7374\" srcset=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-300x167.jpg 300w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-1024x569.jpg 1024w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-768x427.jpg 768w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-1536x853.jpg 1536w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-500x278.jpg 500w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701.jpg 2000w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><br \/>\nI promise that this is the <span style=\"text-decoration:underline\">final post<\/span> dealing with reading a mouse in a terminal window. It&#8217;s a weird thing to do without a specific library in C, but made possible thanks to ANSI codes and the standard I\/O programming necessary to read and store the data.<br \/>\n<!--more--><br \/>\nThe point of pointing and clicking a mouse is to perform some sort of activity at the clicking (or pointing) location. The code from <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7419\">last week&#8217;s Lesson<\/a> swallows, stores, and uses the data. A lot of terminal manipulation happens to accomplish this task; you must properly configure things to capture the endless flow of mouse input. But do these modifications otherwise affect text processing?<\/p>\n<p>The following code is a teensy update to what was presented in last week&#8217;s Lesson. The new action takes place primarily in the <em>main()<\/em> function, in the <em>while<\/em> loop that processes input, both text and mouse:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2026_03_07-Lesson.c\" rel=\"noopener\" target=\"_blank\">2026_03_07-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;ctype.h&gt;\r\n#include &lt;termios.h&gt;\r\n#include &lt;unistd.h&gt;\r\n\r\n#define clear() printf(\"\\e[H\\e[2J\")\r\n#define moveto(a,b) printf(\"\\e[%d;%dH\",b,a)\r\n#define mouse_enable() printf(\"\\e[?1000h\")\r\n#define mouse_motion() printf(\"\\e[?1003h\")\r\n#define mouse_extended() printf(\"\\e[?1006h\")\r\n#define mouse_disable() printf(\"\\e[?1000l\")\r\n\r\nstruct mouse_data {\r\n    int button;\r\n    int column;\r\n    int row;\r\n};\r\n\r\n<span class=\"comments\">\/* read an integer from a string\r\n   Exercise 2026_02 *\/<\/span>\r\nchar *extract(char *s)\r\n{\r\n    static char *sp;\r\n\r\n    <span class=\"comments\">\/* check for recall *\/<\/span>\r\n    if( s != NULL )\r\n        sp = s;\r\n    else\r\n        while( isdigit(*sp) )\r\n            sp++;\r\n\r\n    <span class=\"comments\">\/* find the next digit *\/<\/span>\r\n    while( *sp != '\\0' )\r\n    {\r\n        if( isdigit(*sp) )\r\n        {\r\n            return(sp);\r\n        }\r\n        sp++;\r\n    }\r\n\r\n    return(NULL);\r\n}\r\n\r\n<span class=\"comments\">\/* obtain values from mouse data *\/<\/span>\r\nvoid read_mouse(char *b, struct mouse_data *m)\r\n{\r\n    m-&gt;button = atoi(extract(b));\r\n    m-&gt;column = atoi(extract(NULL));\r\n    m-&gt;row = atoi(extract(NULL));\r\n}\r\n\r\nint main()\r\n{\r\n    struct termios original,noecho;\r\n    struct mouse_data mickey;\r\n    char buffer[13];\r\n    int key;\r\n\r\n    <span class=\"comments\">\/* obtain terminal configuration *\/<\/span>\r\n    tcgetattr(fileno(stdin),&amp;original);\r\n    noecho = original;        <span class=\"comments\">\/* duplicate *\/<\/span>\r\n        <span class=\"comments\">\/* enable raw input *\/<\/span>\r\n    noecho.c_lflag = noecho.c_lflag ^ ICANON;\r\n        <span class=\"comments\">\/* disable full duplex *\/<\/span>\r\n    noecho.c_lflag = noecho.c_lflag ^ ECHO;\r\n        <span class=\"comments\">\/* update terminal definition *\/<\/span>\r\n    tcsetattr(fileno(stdin), TCSANOW, &amp;noecho);\r\n\r\n    <span class=\"comments\">\/* enable mouse reporting *\/<\/span>\r\n    mouse_enable();\r\n    mouse_motion();\r\n    mouse_extended();\r\n    <span class=\"comments\">\/* remove line buffering *\/<\/span>\r\n    setvbuf(stdin,NULL,_IONBF,0);\r\n\r\n    <span class=\"comments\">\/* read stdin *\/<\/span>\r\n    clear();\r\n    puts(\"Play with the mouse; press Enter to end\");\r\n    while( (key=getchar()) != '\\n' )\r\n    {\r\n        if( key==0x1b )\r\n        {\r\n            read(fileno(stdin),buffer,12);\r\n            buffer[12] = '\\0';        <span class=\"comments\">\/* make it a string *\/<\/span>\r\n            read_mouse(buffer,&amp;mickey);\r\n            if( mickey.button == 0 )\r\n                moveto(mickey.column,mickey.row);\r\n        }\r\n        else\r\n            putchar(key);\r\n    }\r\n\r\n    <span class=\"comments\">\/* clean-up *\/<\/span>\r\n    moveto(1,2);        <span class=\"comments\">\/* setup the cursor *\/<\/span>\r\n    mouse_disable();    <span class=\"comments\">\/* disable mouse reporting *\/<\/span>\r\n    tcsetattr(fileno(stdin), TCSANOW, &amp;original);\r\n    return 0;\r\n}<\/pre>\n<p>The issue presented in this code is to determine whether input is coming from the mouse or is generated by the keyboard. I&#8217;m certain that a more sophisticated way exists to make this determination, but I&#8217;m sticking with streaming input. So, both mouse data and keyboard data arrive via the <em>getchar()<\/em> function, which is part of the <em>while<\/em> loop&#8217;s condition:<\/p>\n<p><code>while( (key=getchar()) != '\\n' )<\/code><\/p>\n<p>To determine whether the input is an ANSI mouse sequence, an <em>if<\/em> test checks for the escape character:<\/p>\n<p><code>if( key==0x1b )<\/code><\/p>\n<p>When true, 12 characters are read from standard input and processed. No action is taken unless the value of the mouse button pressed is zero, meaning a left (main) click: <code>if( mickey.button == 0 )<\/code> If so, the cursor is relocated to the mouse click position in the terminal window: <code>moveto(mickey.column,mickey.row);<\/code><\/p>\n<p>When the escape key isn&#8217;t pressed, the character input is sent to standard output: <code>putchar(key);<\/code>. The effect is that you can click the mouse in the terminal window and then type some text. But keep in mind that when you press the Enter key, the program stops.<\/p>\n<p>Figure 1 illustrates a sample run.<\/p>\n<div id=\"attachment_7441\" style=\"width: 650px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-7441\" src=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/02\/0307.gif\" alt=\"terminal window animation showing mouse movement and text\" width=\"640\" height=\"427\" class=\"size-full wp-image-7441\" \/><p id=\"caption-attachment-7441\" class=\"wp-caption-text\">Figure 1. The program&#8217;s output: Click the mouse, type some text.<\/p><\/div>\n<p>I enjoyed working through this series and coming up with all the fun code to read the mouse and do things with its input. But, seriously, if you need to program the mouse or do mousey things in a terminal window, I highly recommend that you use the Ncurses library to allow for consistency and reliability.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Point. Click. And Type. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7440\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-7440","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7440","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7440"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7440\/revisions"}],"predecessor-version":[{"id":7456,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7440\/revisions\/7456"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7440"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7440"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7440"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}