1262685Sdelphij<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> 2262685Sdelphij<HTML 3262685Sdelphij><HEAD 4262685Sdelphij><TITLE 5262685Sdelphij> NCURSES Programming HOWTO </TITLE 6262685Sdelphij><META 7262685SdelphijNAME="GENERATOR" 8262685SdelphijCONTENT="Modular DocBook HTML Stylesheet Version 1.79"></HEAD 9262685Sdelphij><BODY 10262685SdelphijCLASS="ARTICLE" 11262685SdelphijBGCOLOR="#FFFFFF" 12262685SdelphijTEXT="#000000" 13262685SdelphijLINK="#0000FF" 14262685SdelphijVLINK="#840084" 15262685SdelphijALINK="#0000FF" 16262685Sdelphij><DIV 17262685SdelphijCLASS="ARTICLE" 18262685Sdelphij><DIV 19262685SdelphijCLASS="TITLEPAGE" 20262685Sdelphij><H1 21262685SdelphijCLASS="TITLE" 22262685Sdelphij><A 23262685SdelphijNAME="AEN2" 24262685Sdelphij>NCURSES Programming HOWTO</A 25262685Sdelphij></H1 26262685Sdelphij><H3 27262685SdelphijCLASS="AUTHOR" 28262685Sdelphij><A 29262685SdelphijNAME="AEN4" 30262685Sdelphij> Pradeep Padala </A 31262685Sdelphij></H3 32262685Sdelphij><DIV 33262685SdelphijCLASS="AFFILIATION" 34262685Sdelphij><DIV 35262685SdelphijCLASS="ADDRESS" 36262685Sdelphij><P 37262685SdelphijCLASS="ADDRESS" 38262685Sdelphij><CODE 39262685SdelphijCLASS="EMAIL" 40262685Sdelphij><<A 41262685SdelphijHREF="mailto:ppadala@gmail.com" 42262685Sdelphij>ppadala@gmail.com</A 43262685Sdelphij>></CODE 44262685Sdelphij></P 45262685Sdelphij></DIV 46262685Sdelphij></DIV 47262685Sdelphij><P 48262685SdelphijCLASS="PUBDATE" 49262685Sdelphij>v1.9, 2005-06-20<BR></P 50262685Sdelphij><DIV 51262685SdelphijCLASS="REVHISTORY" 52262685Sdelphij><TABLE 53262685SdelphijWIDTH="100%" 54262685SdelphijBORDER="0" 55262685Sdelphij><TR 56262685Sdelphij><TH 57262685SdelphijALIGN="LEFT" 58262685SdelphijVALIGN="TOP" 59262685SdelphijCOLSPAN="3" 60262685Sdelphij><B 61262685Sdelphij>Revision History</B 62262685Sdelphij></TH 63262685Sdelphij></TR 64262685Sdelphij><TR 65262685Sdelphij><TD 66262685SdelphijALIGN="LEFT" 67262685Sdelphij>Revision 1.9</TD 68262685Sdelphij><TD 69262685SdelphijALIGN="LEFT" 70262685Sdelphij>2005-06-20</TD 71262685Sdelphij><TD 72262685SdelphijALIGN="LEFT" 73262685Sdelphij>Revised by: ppadala</TD 74262685Sdelphij></TR 75262685Sdelphij><TR 76262685Sdelphij><TD 77262685SdelphijALIGN="LEFT" 78262685SdelphijCOLSPAN="3" 79262685Sdelphij>The license has been changed to the MIT-style license used 80262685Sdelphij by NCURSES. Note that the programs are also re-licensed under this.</TD 81262685Sdelphij></TR 82262685Sdelphij><TR 83262685Sdelphij><TD 84262685SdelphijALIGN="LEFT" 85262685Sdelphij>Revision 1.8</TD 86262685Sdelphij><TD 87262685SdelphijALIGN="LEFT" 88262685Sdelphij>2005-06-17</TD 89262685Sdelphij><TD 90262685SdelphijALIGN="LEFT" 91262685Sdelphij>Revised by: ppadala</TD 92262685Sdelphij></TR 93262685Sdelphij><TR 94262685Sdelphij><TD 95262685SdelphijALIGN="LEFT" 96262685SdelphijCOLSPAN="3" 97262685Sdelphij>Lots of updates. Added references and perl examples. 98262685Sdelphij Changes to examples. Many grammatical and stylistic changes to the 99262685Sdelphij content. Changes to NCURSES history.</TD 100262685Sdelphij></TR 101262685Sdelphij><TR 102262685Sdelphij><TD 103262685SdelphijALIGN="LEFT" 104262685Sdelphij>Revision 1.7.1</TD 105262685Sdelphij><TD 106262685SdelphijALIGN="LEFT" 107262685Sdelphij>2002-06-25</TD 108262685Sdelphij><TD 109262685SdelphijALIGN="LEFT" 110262685Sdelphij>Revised by: ppadala</TD 111262685Sdelphij></TR 112262685Sdelphij><TR 113262685Sdelphij><TD 114262685SdelphijALIGN="LEFT" 115262685SdelphijCOLSPAN="3" 116262685Sdelphij>Added a README file for building and instructions 117262685Sdelphij for building from source.</TD 118262685Sdelphij></TR 119262685Sdelphij><TR 120262685Sdelphij><TD 121262685SdelphijALIGN="LEFT" 122262685Sdelphij>Revision 1.7</TD 123262685Sdelphij><TD 124262685SdelphijALIGN="LEFT" 125262685Sdelphij>2002-06-25</TD 126262685Sdelphij><TD 127262685SdelphijALIGN="LEFT" 128262685Sdelphij>Revised by: ppadala</TD 129262685Sdelphij></TR 130262685Sdelphij><TR 131262685Sdelphij><TD 132262685SdelphijALIGN="LEFT" 133262685SdelphijCOLSPAN="3" 134262685Sdelphij>Added "Other formats" section and made a lot of fancy 135262685Sdelphij changes to the programs. Inlining of programs is gone.</TD 136262685Sdelphij></TR 137262685Sdelphij><TR 138262685Sdelphij><TD 139262685SdelphijALIGN="LEFT" 140262685Sdelphij>Revision 1.6.1</TD 141262685Sdelphij><TD 142262685SdelphijALIGN="LEFT" 143262685Sdelphij>2002-02-24</TD 144262685Sdelphij><TD 145262685SdelphijALIGN="LEFT" 146262685Sdelphij>Revised by: ppadala</TD 147262685Sdelphij></TR 148262685Sdelphij><TR 149262685Sdelphij><TD 150262685SdelphijALIGN="LEFT" 151262685SdelphijCOLSPAN="3" 152262685Sdelphij>Removed the old Changelog section, cleaned the makefiles</TD 153262685Sdelphij></TR 154262685Sdelphij><TR 155262685Sdelphij><TD 156262685SdelphijALIGN="LEFT" 157262685Sdelphij>Revision 1.6</TD 158262685Sdelphij><TD 159262685SdelphijALIGN="LEFT" 160262685Sdelphij>2002-02-16</TD 161262685Sdelphij><TD 162262685SdelphijALIGN="LEFT" 163262685Sdelphij>Revised by: ppadala</TD 164262685Sdelphij></TR 165262685Sdelphij><TR 166262685Sdelphij><TD 167262685SdelphijALIGN="LEFT" 168262685SdelphijCOLSPAN="3" 169262685Sdelphij>Corrected a lot of spelling mistakes, added ACS variables 170262685Sdelphij section</TD 171262685Sdelphij></TR 172262685Sdelphij><TR 173262685Sdelphij><TD 174262685SdelphijALIGN="LEFT" 175262685Sdelphij>Revision 1.5</TD 176262685Sdelphij><TD 177262685SdelphijALIGN="LEFT" 178262685Sdelphij>2002-01-05</TD 179262685Sdelphij><TD 180262685SdelphijALIGN="LEFT" 181262685Sdelphij>Revised by: ppadala</TD 182262685Sdelphij></TR 183262685Sdelphij><TR 184262685Sdelphij><TD 185262685SdelphijALIGN="LEFT" 186262685SdelphijCOLSPAN="3" 187262685Sdelphij>Changed structure to present proper TOC</TD 188262685Sdelphij></TR 189262685Sdelphij><TR 190262685Sdelphij><TD 191262685SdelphijALIGN="LEFT" 192262685Sdelphij>Revision 1.3.1</TD 193262685Sdelphij><TD 194262685SdelphijALIGN="LEFT" 195262685Sdelphij>2001-07-26</TD 196262685Sdelphij><TD 197262685SdelphijALIGN="LEFT" 198262685Sdelphij>Revised by: ppadala</TD 199262685Sdelphij></TR 200262685Sdelphij><TR 201262685Sdelphij><TD 202262685SdelphijALIGN="LEFT" 203262685SdelphijCOLSPAN="3" 204262685Sdelphij>Corrected maintainers paragraph, Corrected stable release number</TD 205262685Sdelphij></TR 206262685Sdelphij><TR 207262685Sdelphij><TD 208262685SdelphijALIGN="LEFT" 209262685Sdelphij>Revision 1.3</TD 210262685Sdelphij><TD 211262685SdelphijALIGN="LEFT" 212262685Sdelphij>2001-07-24</TD 213262685Sdelphij><TD 214262685SdelphijALIGN="LEFT" 215262685Sdelphij>Revised by: ppadala</TD 216262685Sdelphij></TR 217262685Sdelphij><TR 218262685Sdelphij><TD 219262685SdelphijALIGN="LEFT" 220262685SdelphijCOLSPAN="3" 221262685Sdelphij>Added copyright notices to main document (LDP license) 222262685Sdelphij and programs (GPL), Corrected 223262685Sdelphij printw_example.</TD 224262685Sdelphij></TR 225262685Sdelphij><TR 226262685Sdelphij><TD 227262685SdelphijALIGN="LEFT" 228262685Sdelphij>Revision 1.2</TD 229262685Sdelphij><TD 230262685SdelphijALIGN="LEFT" 231262685Sdelphij>2001-06-05</TD 232262685Sdelphij><TD 233262685SdelphijALIGN="LEFT" 234262685Sdelphij>Revised by: ppadala</TD 235262685Sdelphij></TR 236262685Sdelphij><TR 237262685Sdelphij><TD 238262685SdelphijALIGN="LEFT" 239262685SdelphijCOLSPAN="3" 240262685Sdelphij>Incorporated ravi's changes. Mainly to introduction, menu, 241262685Sdelphij form, justforfun sections</TD 242262685Sdelphij></TR 243262685Sdelphij><TR 244262685Sdelphij><TD 245262685SdelphijALIGN="LEFT" 246262685Sdelphij>Revision 1.1</TD 247262685Sdelphij><TD 248262685SdelphijALIGN="LEFT" 249262685Sdelphij>2001-05-22</TD 250262685Sdelphij><TD 251262685SdelphijALIGN="LEFT" 252262685Sdelphij>Revised by: ppadala</TD 253262685Sdelphij></TR 254262685Sdelphij><TR 255262685Sdelphij><TD 256262685SdelphijALIGN="LEFT" 257262685SdelphijCOLSPAN="3" 258262685Sdelphij>Added "a word about window" section, Added scanw_example.</TD 259262685Sdelphij></TR 260262685Sdelphij></TABLE 261262685Sdelphij></DIV 262262685Sdelphij><DIV 263262685Sdelphij><DIV 264262685SdelphijCLASS="ABSTRACT" 265262685Sdelphij><P 266262685Sdelphij></P 267262685Sdelphij><A 268262685SdelphijNAME="AEN67" 269262685Sdelphij></A 270262685Sdelphij><P 271262685Sdelphij> <SPAN 272262685SdelphijCLASS="emphasis" 273262685Sdelphij><I 274262685SdelphijCLASS="EMPHASIS" 275262685Sdelphij>This document is intended to be an "All in One" guide for programming with 276262685Sdelphijncurses and its sister libraries. We graduate from a simple "Hello World" 277262685Sdelphijprogram to more complex form manipulation. No prior experience in ncurses is 278262685Sdelphijassumed. Send comments to <A 279262685SdelphijHREF="mailto:ppadala@gmail.com" 280262685SdelphijTARGET="_top" 281262685Sdelphij>this address</A 282262685Sdelphij> 283262685Sdelphij </I 284262685Sdelphij></SPAN 285262685Sdelphij> 286262685Sdelphij </P 287262685Sdelphij><P 288262685Sdelphij></P 289262685Sdelphij></DIV 290262685Sdelphij></DIV 291262685Sdelphij><HR></DIV 292262685Sdelphij><DIV 293262685SdelphijCLASS="TOC" 294262685Sdelphij><DL 295262685Sdelphij><DT 296262685Sdelphij><B 297262685Sdelphij>Table of Contents</B 298262685Sdelphij></DT 299262685Sdelphij><DT 300262685Sdelphij>1. <A 301262685SdelphijHREF="#INTRO" 302262685Sdelphij>Introduction</A 303262685Sdelphij></DT 304262685Sdelphij><DD 305262685Sdelphij><DL 306262685Sdelphij><DT 307262685Sdelphij>1.1. <A 308262685SdelphijHREF="#WHATIS" 309262685Sdelphij>What is NCURSES?</A 310262685Sdelphij></DT 311262685Sdelphij><DT 312262685Sdelphij>1.2. <A 313262685SdelphijHREF="#WHATCANWEDO" 314262685Sdelphij>What we can do with NCURSES</A 315262685Sdelphij></DT 316262685Sdelphij><DT 317262685Sdelphij>1.3. <A 318262685SdelphijHREF="#WHERETOGETIT" 319262685Sdelphij>Where to get it</A 320262685Sdelphij></DT 321262685Sdelphij><DT 322262685Sdelphij>1.4. <A 323262685SdelphijHREF="#PURPOSE" 324262685Sdelphij>Purpose/Scope of the document</A 325262685Sdelphij></DT 326262685Sdelphij><DT 327262685Sdelphij>1.5. <A 328262685SdelphijHREF="#ABOUTPROGRAMS" 329262685Sdelphij>About the Programs</A 330262685Sdelphij></DT 331262685Sdelphij><DT 332262685Sdelphij>1.6. <A 333262685SdelphijHREF="#OTHERFORMATS" 334262685Sdelphij>Other Formats of the document</A 335262685Sdelphij></DT 336262685Sdelphij><DD 337262685Sdelphij><DL 338262685Sdelphij><DT 339262685Sdelphij>1.6.1. <A 340262685SdelphijHREF="#LISTFORMATS" 341262685Sdelphij>Readily available formats from tldp.org</A 342262685Sdelphij></DT 343262685Sdelphij><DT 344262685Sdelphij>1.6.2. <A 345262685SdelphijHREF="#BUILDSOURCE" 346262685Sdelphij>Building from source</A 347262685Sdelphij></DT 348262685Sdelphij></DL 349262685Sdelphij></DD 350262685Sdelphij><DT 351262685Sdelphij>1.7. <A 352262685SdelphijHREF="#CREDITS" 353262685Sdelphij>Credits</A 354262685Sdelphij></DT 355262685Sdelphij><DT 356262685Sdelphij>1.8. <A 357262685SdelphijHREF="#WISHLIST" 358262685Sdelphij>Wish List</A 359262685Sdelphij></DT 360262685Sdelphij><DT 361262685Sdelphij>1.9. <A 362262685SdelphijHREF="#COPYRIGHT" 363262685Sdelphij>Copyright</A 364262685Sdelphij></DT 365262685Sdelphij></DL 366262685Sdelphij></DD 367262685Sdelphij><DT 368262685Sdelphij>2. <A 369262685SdelphijHREF="#HELLOWORLD" 370262685Sdelphij>Hello World !!!</A 371262685Sdelphij></DT 372262685Sdelphij><DD 373262685Sdelphij><DL 374262685Sdelphij><DT 375262685Sdelphij>2.1. <A 376262685SdelphijHREF="#COMPILECURSES" 377262685Sdelphij>Compiling With the NCURSES Library</A 378262685Sdelphij></DT 379262685Sdelphij><DT 380262685Sdelphij>2.2. <A 381262685SdelphijHREF="#DISSECTION" 382262685Sdelphij>Dissection</A 383262685Sdelphij></DT 384262685Sdelphij><DD 385262685Sdelphij><DL 386262685Sdelphij><DT 387262685Sdelphij>2.2.1. <A 388262685SdelphijHREF="#ABOUT-INITSCR" 389262685Sdelphij>About initscr()</A 390262685Sdelphij></DT 391262685Sdelphij><DT 392262685Sdelphij>2.2.2. <A 393262685SdelphijHREF="#MYST-REFRESH" 394262685Sdelphij>The mysterious refresh()</A 395262685Sdelphij></DT 396262685Sdelphij><DT 397262685Sdelphij>2.2.3. <A 398262685SdelphijHREF="#ABOUT-ENDWIN" 399262685Sdelphij>About endwin()</A 400262685Sdelphij></DT 401262685Sdelphij></DL 402262685Sdelphij></DD 403262685Sdelphij></DL 404262685Sdelphij></DD 405262685Sdelphij><DT 406262685Sdelphij>3. <A 407262685SdelphijHREF="#GORY" 408262685Sdelphij>The Gory Details</A 409262685Sdelphij></DT 410262685Sdelphij><DT 411262685Sdelphij>4. <A 412262685SdelphijHREF="#INIT" 413262685Sdelphij>Initialization</A 414262685Sdelphij></DT 415262685Sdelphij><DD 416262685Sdelphij><DL 417262685Sdelphij><DT 418262685Sdelphij>4.1. <A 419262685SdelphijHREF="#ABOUTINIT" 420262685Sdelphij>Initialization functions</A 421262685Sdelphij></DT 422262685Sdelphij><DT 423262685Sdelphij>4.2. <A 424262685SdelphijHREF="#RAWCBREAK" 425262685Sdelphij>raw() and cbreak()</A 426262685Sdelphij></DT 427262685Sdelphij><DT 428262685Sdelphij>4.3. <A 429262685SdelphijHREF="#ECHONOECHO" 430262685Sdelphij>echo() and noecho()</A 431262685Sdelphij></DT 432262685Sdelphij><DT 433262685Sdelphij>4.4. <A 434262685SdelphijHREF="#KEYPAD" 435262685Sdelphij>keypad()</A 436262685Sdelphij></DT 437262685Sdelphij><DT 438262685Sdelphij>4.5. <A 439262685SdelphijHREF="#HALFDELAY" 440262685Sdelphij>halfdelay()</A 441262685Sdelphij></DT 442262685Sdelphij><DT 443262685Sdelphij>4.6. <A 444262685SdelphijHREF="#MISCINIT" 445262685Sdelphij>Miscellaneous Initialization functions</A 446262685Sdelphij></DT 447262685Sdelphij><DT 448262685Sdelphij>4.7. <A 449262685SdelphijHREF="#INITEX" 450262685Sdelphij>An Example</A 451262685Sdelphij></DT 452262685Sdelphij></DL 453262685Sdelphij></DD 454262685Sdelphij><DT 455262685Sdelphij>5. <A 456262685SdelphijHREF="#AWORDWINDOWS" 457262685Sdelphij>A Word about Windows</A 458262685Sdelphij></DT 459262685Sdelphij><DT 460262685Sdelphij>6. <A 461262685SdelphijHREF="#PRINTW" 462262685Sdelphij>Output functions</A 463262685Sdelphij></DT 464262685Sdelphij><DD 465262685Sdelphij><DL 466262685Sdelphij><DT 467262685Sdelphij>6.1. <A 468262685SdelphijHREF="#ADDCHCLASS" 469262685Sdelphij>addch() class of functions</A 470262685Sdelphij></DT 471262685Sdelphij><DT 472262685Sdelphij>6.2. <A 473262685SdelphijHREF="#AEN298" 474262685Sdelphij>mvaddch(), waddch() and mvwaddch()</A 475262685Sdelphij></DT 476262685Sdelphij><DT 477262685Sdelphij>6.3. <A 478262685SdelphijHREF="#PRINTWCLASS" 479262685Sdelphij>printw() class of functions</A 480262685Sdelphij></DT 481262685Sdelphij><DD 482262685Sdelphij><DL 483262685Sdelphij><DT 484262685Sdelphij>6.3.1. <A 485262685SdelphijHREF="#PRINTWMVPRINTW" 486262685Sdelphij>printw() and mvprintw</A 487262685Sdelphij></DT 488262685Sdelphij><DT 489262685Sdelphij>6.3.2. <A 490262685SdelphijHREF="#WPRINTWMVWPRINTW" 491262685Sdelphij>wprintw() and mvwprintw</A 492262685Sdelphij></DT 493262685Sdelphij><DT 494262685Sdelphij>6.3.3. <A 495262685SdelphijHREF="#VWPRINTW" 496262685Sdelphij>vwprintw()</A 497262685Sdelphij></DT 498262685Sdelphij><DT 499262685Sdelphij>6.3.4. <A 500262685SdelphijHREF="#SIMPLEPRINTWEX" 501262685Sdelphij>A Simple printw example</A 502262685Sdelphij></DT 503262685Sdelphij></DL 504262685Sdelphij></DD 505262685Sdelphij><DT 506262685Sdelphij>6.4. <A 507262685SdelphijHREF="#ADDSTRCLASS" 508262685Sdelphij>addstr() class of functions</A 509262685Sdelphij></DT 510262685Sdelphij><DT 511262685Sdelphij>6.5. <A 512262685SdelphijHREF="#ACAUTION" 513262685Sdelphij>A word of caution</A 514262685Sdelphij></DT 515262685Sdelphij></DL 516262685Sdelphij></DD 517262685Sdelphij><DT 518262685Sdelphij>7. <A 519262685SdelphijHREF="#SCANW" 520262685Sdelphij>Input functions</A 521262685Sdelphij></DT 522262685Sdelphij><DD 523262685Sdelphij><DL 524262685Sdelphij><DT 525262685Sdelphij>7.1. <A 526262685SdelphijHREF="#GETCHCLASS" 527262685Sdelphij>getch() class of functions</A 528262685Sdelphij></DT 529262685Sdelphij><DT 530262685Sdelphij>7.2. <A 531262685SdelphijHREF="#SCANWCLASS" 532262685Sdelphij>scanw() class of functions</A 533262685Sdelphij></DT 534262685Sdelphij><DD 535262685Sdelphij><DL 536262685Sdelphij><DT 537262685Sdelphij>7.2.1. <A 538262685SdelphijHREF="#SCANWMVSCANW" 539262685Sdelphij>scanw() and mvscanw</A 540262685Sdelphij></DT 541262685Sdelphij><DT 542262685Sdelphij>7.2.2. <A 543262685SdelphijHREF="#WSCANWMVWSCANW" 544262685Sdelphij>wscanw() and mvwscanw()</A 545262685Sdelphij></DT 546262685Sdelphij><DT 547262685Sdelphij>7.2.3. <A 548262685SdelphijHREF="#VWSCANW" 549262685Sdelphij>vwscanw()</A 550262685Sdelphij></DT 551262685Sdelphij></DL 552262685Sdelphij></DD 553262685Sdelphij><DT 554262685Sdelphij>7.3. <A 555262685SdelphijHREF="#GETSTRCLASS" 556262685Sdelphij>getstr() class of functions</A 557262685Sdelphij></DT 558262685Sdelphij><DT 559262685Sdelphij>7.4. <A 560262685SdelphijHREF="#GETSTREX" 561262685Sdelphij>Some examples</A 562262685Sdelphij></DT 563262685Sdelphij></DL 564262685Sdelphij></DD 565262685Sdelphij><DT 566262685Sdelphij>8. <A 567262685SdelphijHREF="#ATTRIB" 568262685Sdelphij>Attributes</A 569262685Sdelphij></DT 570262685Sdelphij><DD 571262685Sdelphij><DL 572262685Sdelphij><DT 573262685Sdelphij>8.1. <A 574262685SdelphijHREF="#ATTRIBDETAILS" 575262685Sdelphij>The details</A 576262685Sdelphij></DT 577262685Sdelphij><DT 578262685Sdelphij>8.2. <A 579262685SdelphijHREF="#ATTRONVSATTRSET" 580262685Sdelphij>attron() vs attrset()</A 581262685Sdelphij></DT 582262685Sdelphij><DT 583262685Sdelphij>8.3. <A 584262685SdelphijHREF="#ATTR_GET" 585262685Sdelphij>attr_get()</A 586262685Sdelphij></DT 587262685Sdelphij><DT 588262685Sdelphij>8.4. <A 589262685SdelphijHREF="#ATTR_FUNCS" 590262685Sdelphij>attr_ functions</A 591262685Sdelphij></DT 592262685Sdelphij><DT 593262685Sdelphij>8.5. <A 594262685SdelphijHREF="#WATTRFUNCS" 595262685Sdelphij>wattr functions</A 596262685Sdelphij></DT 597262685Sdelphij><DT 598262685Sdelphij>8.6. <A 599262685SdelphijHREF="#CHGAT" 600262685Sdelphij>chgat() functions</A 601262685Sdelphij></DT 602262685Sdelphij></DL 603262685Sdelphij></DD 604262685Sdelphij><DT 605262685Sdelphij>9. <A 606262685SdelphijHREF="#WINDOWS" 607262685Sdelphij>Windows</A 608262685Sdelphij></DT 609262685Sdelphij><DD 610262685Sdelphij><DL 611262685Sdelphij><DT 612262685Sdelphij>9.1. <A 613262685SdelphijHREF="#WINDOWBASICS" 614262685Sdelphij>The basics</A 615262685Sdelphij></DT 616262685Sdelphij><DT 617262685Sdelphij>9.2. <A 618262685SdelphijHREF="#LETBEWINDOW" 619262685Sdelphij>Let there be a Window !!!</A 620262685Sdelphij></DT 621262685Sdelphij><DT 622262685Sdelphij>9.3. <A 623262685SdelphijHREF="#BORDEREXEXPL" 624262685Sdelphij>Explanation</A 625262685Sdelphij></DT 626262685Sdelphij><DT 627262685Sdelphij>9.4. <A 628262685SdelphijHREF="#OTHERSTUFF" 629262685Sdelphij>The other stuff in the example</A 630262685Sdelphij></DT 631262685Sdelphij><DT 632262685Sdelphij>9.5. <A 633262685SdelphijHREF="#OTHERBORDERFUNCS" 634262685Sdelphij>Other Border functions</A 635262685Sdelphij></DT 636262685Sdelphij></DL 637262685Sdelphij></DD 638262685Sdelphij><DT 639262685Sdelphij>10. <A 640262685SdelphijHREF="#COLOR" 641262685Sdelphij>Colors</A 642262685Sdelphij></DT 643262685Sdelphij><DD 644262685Sdelphij><DL 645262685Sdelphij><DT 646262685Sdelphij>10.1. <A 647262685SdelphijHREF="#COLORBASICS" 648262685Sdelphij>The basics</A 649262685Sdelphij></DT 650262685Sdelphij><DT 651262685Sdelphij>10.2. <A 652262685SdelphijHREF="#CHANGECOLORDEFS" 653262685Sdelphij>Changing Color Definitions</A 654262685Sdelphij></DT 655262685Sdelphij><DT 656262685Sdelphij>10.3. <A 657262685SdelphijHREF="#COLORCONTENT" 658262685Sdelphij>Color Content</A 659262685Sdelphij></DT 660262685Sdelphij></DL 661262685Sdelphij></DD 662262685Sdelphij><DT 663262685Sdelphij>11. <A 664262685SdelphijHREF="#KEYS" 665262685Sdelphij>Interfacing with the key board</A 666262685Sdelphij></DT 667262685Sdelphij><DD 668262685Sdelphij><DL 669262685Sdelphij><DT 670262685Sdelphij>11.1. <A 671262685SdelphijHREF="#KEYSBASICS" 672262685Sdelphij>The Basics</A 673262685Sdelphij></DT 674262685Sdelphij><DT 675262685Sdelphij>11.2. <A 676262685SdelphijHREF="#SIMPLEKEYEX" 677262685Sdelphij>A Simple Key Usage example</A 678262685Sdelphij></DT 679262685Sdelphij></DL 680262685Sdelphij></DD 681262685Sdelphij><DT 682262685Sdelphij>12. <A 683262685SdelphijHREF="#MOUSE" 684262685Sdelphij>Interfacing with the mouse</A 685262685Sdelphij></DT 686262685Sdelphij><DD 687262685Sdelphij><DL 688262685Sdelphij><DT 689262685Sdelphij>12.1. <A 690262685SdelphijHREF="#MOUSEBASICS" 691262685Sdelphij>The Basics</A 692262685Sdelphij></DT 693262685Sdelphij><DT 694262685Sdelphij>12.2. <A 695262685SdelphijHREF="#GETTINGEVENTS" 696262685Sdelphij>Getting the events</A 697262685Sdelphij></DT 698262685Sdelphij><DT 699262685Sdelphij>12.3. <A 700262685SdelphijHREF="#MOUSETOGETHER" 701262685Sdelphij>Putting it all Together</A 702262685Sdelphij></DT 703262685Sdelphij><DT 704262685Sdelphij>12.4. <A 705262685SdelphijHREF="#MISCMOUSEFUNCS" 706262685Sdelphij>Miscellaneous Functions</A 707262685Sdelphij></DT 708262685Sdelphij></DL 709262685Sdelphij></DD 710262685Sdelphij><DT 711262685Sdelphij>13. <A 712262685SdelphijHREF="#SCREEN" 713262685Sdelphij>Screen Manipulation</A 714262685Sdelphij></DT 715262685Sdelphij><DD 716262685Sdelphij><DL 717262685Sdelphij><DT 718262685Sdelphij>13.1. <A 719262685SdelphijHREF="#GETYX" 720262685Sdelphij>getyx() functions</A 721262685Sdelphij></DT 722262685Sdelphij><DT 723262685Sdelphij>13.2. <A 724262685SdelphijHREF="#SCREENDUMP" 725262685Sdelphij>Screen Dumping</A 726262685Sdelphij></DT 727262685Sdelphij><DT 728262685Sdelphij>13.3. <A 729262685SdelphijHREF="#WINDOWDUMP" 730262685Sdelphij>Window Dumping</A 731262685Sdelphij></DT 732262685Sdelphij></DL 733262685Sdelphij></DD 734262685Sdelphij><DT 735262685Sdelphij>14. <A 736262685SdelphijHREF="#MISC" 737262685Sdelphij>Miscellaneous features</A 738262685Sdelphij></DT 739262685Sdelphij><DD 740262685Sdelphij><DL 741262685Sdelphij><DT 742262685Sdelphij>14.1. <A 743262685SdelphijHREF="#CURSSET" 744262685Sdelphij>curs_set()</A 745262685Sdelphij></DT 746262685Sdelphij><DT 747262685Sdelphij>14.2. <A 748262685SdelphijHREF="#TEMPLEAVE" 749262685Sdelphij>Temporarily Leaving Curses mode</A 750262685Sdelphij></DT 751262685Sdelphij><DT 752262685Sdelphij>14.3. <A 753262685SdelphijHREF="#ACSVARS" 754262685Sdelphij>ACS_ variables</A 755262685Sdelphij></DT 756262685Sdelphij></DL 757262685Sdelphij></DD 758262685Sdelphij><DT 759262685Sdelphij>15. <A 760262685SdelphijHREF="#OTHERLIB" 761262685Sdelphij>Other libraries</A 762262685Sdelphij></DT 763262685Sdelphij><DT 764262685Sdelphij>16. <A 765262685SdelphijHREF="#PANELS" 766262685Sdelphij>Panel Library</A 767262685Sdelphij></DT 768262685Sdelphij><DD 769262685Sdelphij><DL 770262685Sdelphij><DT 771262685Sdelphij>16.1. <A 772262685SdelphijHREF="#PANELBASICS" 773262685Sdelphij>The Basics</A 774262685Sdelphij></DT 775262685Sdelphij><DT 776262685Sdelphij>16.2. <A 777262685SdelphijHREF="#COMPILEPANELS" 778262685Sdelphij>Compiling With the Panels Library</A 779262685Sdelphij></DT 780262685Sdelphij><DT 781262685Sdelphij>16.3. <A 782262685SdelphijHREF="#PANELBROWSING" 783262685Sdelphij>Panel Window Browsing</A 784262685Sdelphij></DT 785262685Sdelphij><DT 786262685Sdelphij>16.4. <A 787262685SdelphijHREF="#USERPTRUSING" 788262685Sdelphij>Using User Pointers</A 789262685Sdelphij></DT 790262685Sdelphij><DT 791262685Sdelphij>16.5. <A 792262685SdelphijHREF="#PANELMOVERESIZE" 793262685Sdelphij>Moving and Resizing Panels</A 794262685Sdelphij></DT 795262685Sdelphij><DT 796262685Sdelphij>16.6. <A 797262685SdelphijHREF="#PANELSHOWHIDE" 798262685Sdelphij>Hiding and Showing Panels</A 799262685Sdelphij></DT 800262685Sdelphij><DT 801262685Sdelphij>16.7. <A 802262685SdelphijHREF="#PANELABOVE" 803262685Sdelphij>panel_above() and panel_below() Functions</A 804262685Sdelphij></DT 805262685Sdelphij></DL 806262685Sdelphij></DD 807262685Sdelphij><DT 808262685Sdelphij>17. <A 809262685SdelphijHREF="#MENUS" 810262685Sdelphij>Menus Library</A 811262685Sdelphij></DT 812262685Sdelphij><DD 813262685Sdelphij><DL 814262685Sdelphij><DT 815262685Sdelphij>17.1. <A 816262685SdelphijHREF="#MENUBASICS" 817262685Sdelphij>The Basics</A 818262685Sdelphij></DT 819262685Sdelphij><DT 820262685Sdelphij>17.2. <A 821262685SdelphijHREF="#COMPILEMENUS" 822262685Sdelphij>Compiling With the Menu Library</A 823262685Sdelphij></DT 824262685Sdelphij><DT 825262685Sdelphij>17.3. <A 826262685SdelphijHREF="#MENUDRIVER" 827262685Sdelphij>Menu Driver: The work horse of the menu system</A 828262685Sdelphij></DT 829262685Sdelphij><DT 830262685Sdelphij>17.4. <A 831262685SdelphijHREF="#MENUWINDOWS" 832262685Sdelphij>Menu Windows</A 833262685Sdelphij></DT 834262685Sdelphij><DT 835262685Sdelphij>17.5. <A 836262685SdelphijHREF="#SCROLLMENUS" 837262685Sdelphij>Scrolling Menus</A 838262685Sdelphij></DT 839262685Sdelphij><DT 840262685Sdelphij>17.6. <A 841262685SdelphijHREF="#MULTICOLUMN" 842262685Sdelphij>Multi Columnar Menus</A 843262685Sdelphij></DT 844262685Sdelphij><DT 845262685Sdelphij>17.7. <A 846262685SdelphijHREF="#MULTIVALUEMENUS" 847262685Sdelphij>Multi Valued Menus</A 848262685Sdelphij></DT 849262685Sdelphij><DT 850262685Sdelphij>17.8. <A 851262685SdelphijHREF="#MENUOPT" 852262685Sdelphij>Menu Options</A 853262685Sdelphij></DT 854262685Sdelphij><DT 855262685Sdelphij>17.9. <A 856262685SdelphijHREF="#MENUUSERPTR" 857262685Sdelphij>The useful User Pointer</A 858262685Sdelphij></DT 859262685Sdelphij></DL 860262685Sdelphij></DD 861262685Sdelphij><DT 862262685Sdelphij>18. <A 863262685SdelphijHREF="#FORMS" 864262685Sdelphij>Forms Library</A 865262685Sdelphij></DT 866262685Sdelphij><DD 867262685Sdelphij><DL 868262685Sdelphij><DT 869262685Sdelphij>18.1. <A 870262685SdelphijHREF="#FORMBASICS" 871262685Sdelphij>The Basics</A 872262685Sdelphij></DT 873262685Sdelphij><DT 874262685Sdelphij>18.2. <A 875262685SdelphijHREF="#COMPILEFORMS" 876262685Sdelphij>Compiling With the Forms Library</A 877262685Sdelphij></DT 878262685Sdelphij><DT 879262685Sdelphij>18.3. <A 880262685SdelphijHREF="#PLAYFIELDS" 881262685Sdelphij>Playing with Fields</A 882262685Sdelphij></DT 883262685Sdelphij><DD 884262685Sdelphij><DL 885262685Sdelphij><DT 886262685Sdelphij>18.3.1. <A 887262685SdelphijHREF="#FETCHINFO" 888262685Sdelphij>Fetching Size and Location of Field</A 889262685Sdelphij></DT 890262685Sdelphij><DT 891262685Sdelphij>18.3.2. <A 892262685SdelphijHREF="#MOVEFIELD" 893262685Sdelphij>Moving the field</A 894262685Sdelphij></DT 895262685Sdelphij><DT 896262685Sdelphij>18.3.3. <A 897262685SdelphijHREF="#JUSTIFYFIELD" 898262685Sdelphij>Field Justification</A 899262685Sdelphij></DT 900262685Sdelphij><DT 901262685Sdelphij>18.3.4. <A 902262685SdelphijHREF="#FIELDDISPATTRIB" 903262685Sdelphij>Field Display Attributes</A 904262685Sdelphij></DT 905262685Sdelphij><DT 906262685Sdelphij>18.3.5. <A 907262685SdelphijHREF="#FIELDOPTIONBITS" 908262685Sdelphij>Field Option Bits</A 909262685Sdelphij></DT 910262685Sdelphij><DT 911262685Sdelphij>18.3.6. <A 912262685SdelphijHREF="#FIELDSTATUS" 913262685Sdelphij>Field Status</A 914262685Sdelphij></DT 915262685Sdelphij><DT 916262685Sdelphij>18.3.7. <A 917262685SdelphijHREF="#FIELDUSERPTR" 918262685Sdelphij>Field User Pointer</A 919262685Sdelphij></DT 920262685Sdelphij><DT 921262685Sdelphij>18.3.8. <A 922262685SdelphijHREF="#VARIABLESIZEFIELDS" 923262685Sdelphij>Variable-Sized Fields</A 924262685Sdelphij></DT 925262685Sdelphij></DL 926262685Sdelphij></DD 927262685Sdelphij><DT 928262685Sdelphij>18.4. <A 929262685SdelphijHREF="#FORMWINDOWS" 930262685Sdelphij>Form Windows</A 931262685Sdelphij></DT 932262685Sdelphij><DT 933262685Sdelphij>18.5. <A 934262685SdelphijHREF="#FILEDVALIDATE" 935262685Sdelphij>Field Validation</A 936262685Sdelphij></DT 937262685Sdelphij><DT 938262685Sdelphij>18.6. <A 939262685SdelphijHREF="#FORMDRIVER" 940262685Sdelphij>Form Driver: The work horse of the forms system</A 941262685Sdelphij></DT 942262685Sdelphij><DD 943262685Sdelphij><DL 944262685Sdelphij><DT 945262685Sdelphij>18.6.1. <A 946262685SdelphijHREF="#PAGENAVREQ" 947262685Sdelphij>Page Navigation Requests</A 948262685Sdelphij></DT 949262685Sdelphij><DT 950262685Sdelphij>18.6.2. <A 951262685SdelphijHREF="#INTERFIELDNAVREQ" 952262685Sdelphij>Inter-Field Navigation Requests</A 953262685Sdelphij></DT 954262685Sdelphij><DT 955262685Sdelphij>18.6.3. <A 956262685SdelphijHREF="#INTRAFIELDNAVREQ" 957262685Sdelphij>Intra-Field Navigation Requests</A 958262685Sdelphij></DT 959262685Sdelphij><DT 960262685Sdelphij>18.6.4. <A 961262685SdelphijHREF="#SCROLLREQ" 962262685Sdelphij>Scrolling Requests</A 963262685Sdelphij></DT 964262685Sdelphij><DT 965262685Sdelphij>18.6.5. <A 966262685SdelphijHREF="#EDITREQ" 967262685Sdelphij>Editing Requests</A 968262685Sdelphij></DT 969262685Sdelphij><DT 970262685Sdelphij>18.6.6. <A 971262685SdelphijHREF="#ORDERREQ" 972262685Sdelphij>Order Requests</A 973262685Sdelphij></DT 974262685Sdelphij><DT 975262685Sdelphij>18.6.7. <A 976262685SdelphijHREF="#APPLICCOMMANDS" 977262685Sdelphij>Application Commands</A 978262685Sdelphij></DT 979262685Sdelphij></DL 980262685Sdelphij></DD 981262685Sdelphij></DL 982262685Sdelphij></DD 983262685Sdelphij><DT 984262685Sdelphij>19. <A 985262685SdelphijHREF="#TOOLS" 986262685Sdelphij>Tools and Widget Libraries</A 987262685Sdelphij></DT 988262685Sdelphij><DD 989262685Sdelphij><DL 990262685Sdelphij><DT 991262685Sdelphij>19.1. <A 992262685SdelphijHREF="#CDK" 993262685Sdelphij>CDK (Curses Development Kit)</A 994262685Sdelphij></DT 995262685Sdelphij><DD 996262685Sdelphij><DL 997262685Sdelphij><DT 998262685Sdelphij>19.1.1. <A 999262685SdelphijHREF="#WIDGETLIST" 1000262685Sdelphij>Widget List</A 1001262685Sdelphij></DT 1002262685Sdelphij><DT 1003262685Sdelphij>19.1.2. <A 1004262685SdelphijHREF="#CDKATTRACT" 1005262685Sdelphij>Some Attractive Features</A 1006262685Sdelphij></DT 1007262685Sdelphij><DT 1008262685Sdelphij>19.1.3. <A 1009262685SdelphijHREF="#CDKCONCLUSION" 1010262685Sdelphij>Conclusion</A 1011262685Sdelphij></DT 1012262685Sdelphij></DL 1013262685Sdelphij></DD 1014262685Sdelphij><DT 1015262685Sdelphij>19.2. <A 1016262685SdelphijHREF="#DIALOG" 1017262685Sdelphij>The dialog</A 1018262685Sdelphij></DT 1019262685Sdelphij><DT 1020262685Sdelphij>19.3. <A 1021262685SdelphijHREF="#PERLCURSES" 1022262685Sdelphij>Perl Curses Modules CURSES::FORM and CURSES::WIDGETS</A 1023262685Sdelphij></DT 1024262685Sdelphij></DL 1025262685Sdelphij></DD 1026262685Sdelphij><DT 1027262685Sdelphij>20. <A 1028262685SdelphijHREF="#JUSTFORFUN" 1029262685Sdelphij>Just For Fun !!!</A 1030262685Sdelphij></DT 1031262685Sdelphij><DD 1032262685Sdelphij><DL 1033262685Sdelphij><DT 1034262685Sdelphij>20.1. <A 1035262685SdelphijHREF="#GAMEOFLIFE" 1036262685Sdelphij>The Game of Life</A 1037262685Sdelphij></DT 1038262685Sdelphij><DT 1039262685Sdelphij>20.2. <A 1040262685SdelphijHREF="#MAGIC" 1041262685Sdelphij>Magic Square</A 1042262685Sdelphij></DT 1043262685Sdelphij><DT 1044262685Sdelphij>20.3. <A 1045262685SdelphijHREF="#HANOI" 1046262685Sdelphij>Towers of Hanoi</A 1047262685Sdelphij></DT 1048262685Sdelphij><DT 1049262685Sdelphij>20.4. <A 1050262685SdelphijHREF="#QUEENS" 1051262685Sdelphij>Queens Puzzle</A 1052262685Sdelphij></DT 1053262685Sdelphij><DT 1054262685Sdelphij>20.5. <A 1055262685SdelphijHREF="#SHUFFLE" 1056262685Sdelphij>Shuffle</A 1057262685Sdelphij></DT 1058262685Sdelphij><DT 1059262685Sdelphij>20.6. <A 1060262685SdelphijHREF="#TT" 1061262685Sdelphij>Typing Tutor</A 1062262685Sdelphij></DT 1063262685Sdelphij></DL 1064262685Sdelphij></DD 1065262685Sdelphij><DT 1066262685Sdelphij>21. <A 1067262685SdelphijHREF="#REF" 1068262685Sdelphij>References</A 1069262685Sdelphij></DT 1070262685Sdelphij></DL 1071262685Sdelphij></DIV 1072262685Sdelphij><DIV 1073262685SdelphijCLASS="SECT1" 1074262685Sdelphij><H2 1075262685SdelphijCLASS="SECT1" 1076262685Sdelphij><A 1077262685SdelphijNAME="INTRO" 1078262685Sdelphij>1. Introduction</A 1079262685Sdelphij></H2 1080262685Sdelphij><P 1081262685Sdelphij>In the olden days of teletype terminals, terminals were away from computers and 1082262685Sdelphijwere connected to them through serial cables. The terminals could be configured 1083262685Sdelphijby sending a series of bytes. All the capabilities (such as 1084262685Sdelphijmoving the cursor to a new location, erasing part of the screen, scrolling the 1085262685Sdelphijscreen, changing modes etc.) of terminals could be accessed through these 1086262685Sdelphijseries of bytes. These control seeuqnces are usually called escape sequences, 1087262685Sdelphijbecause they start 1088262685Sdelphijwith an escape(0x1B) character. Even today, with proper emulation, we can send 1089262685Sdelphijescape sequences to the emulator and achieve the same effect on a terminal 1090262685Sdelphijwindow.</P 1091262685Sdelphij><P 1092262685Sdelphij>Suppose you wanted to print a line in color. Try typing this on your console.</P 1093262685Sdelphij><PRE 1094262685SdelphijCLASS="PROGRAMLISTING" 1095262685Sdelphij>echo "^[[0;31;40mIn Color"</PRE 1096262685Sdelphij><P 1097262685Sdelphij>The first character is an escape character, which looks like two characters ^ 1098262685Sdelphijand [. To be able to print it, you have to press CTRL+V and then the ESC key. 1099262685SdelphijAll the others are normal printable characters. You should be able to see the 1100262685Sdelphijstring "In Color" in red. It stays that way and to revert back to the original 1101262685Sdelphijmode type this.</P 1102262685Sdelphij><PRE 1103262685SdelphijCLASS="PROGRAMLISTING" 1104262685Sdelphij>echo "^[[0;37;40m"</PRE 1105262685Sdelphij><P 1106262685Sdelphij>Now, what do these magic characters mean? Difficult to comprehend? They might 1107262685Sdelphijeven be different for different terminals. So the designers of UNIX invented a 1108262685Sdelphijmechanism named <TT 1109262685SdelphijCLASS="LITERAL" 1110262685Sdelphij>termcap</TT 1111262685Sdelphij>. It is a file that 1112262685Sdelphijlists all the capabilities of a particular terminal, along with the escape 1113262685Sdelphijsequences needed to achieve a particular effect. In the later years, this was 1114262685Sdelphijreplaced by <TT 1115262685SdelphijCLASS="LITERAL" 1116262685Sdelphij>terminfo</TT 1117262685Sdelphij>. Without delving too 1118262685Sdelphijmuch into details, this mechanism allows application 1119262685Sdelphijprograms to query the terminfo database and obtain the control characters to be 1120262685Sdelphijsent to a terminal or terminal emulator.</P 1121262685Sdelphij><DIV 1122262685SdelphijCLASS="SECT2" 1123262685Sdelphij><HR><H3 1124262685SdelphijCLASS="SECT2" 1125262685Sdelphij><A 1126262685SdelphijNAME="WHATIS" 1127262685Sdelphij>1.1. What is NCURSES?</A 1128262685Sdelphij></H3 1129262685Sdelphij><P 1130262685Sdelphij> 1131262685SdelphijYou might be wondering, what the import of all this technical gibberish is. In 1132262685Sdelphijthe above scenario, every application program is supposed to query the terminfo 1133262685Sdelphijand perform the necessary stuff (sending control characters etc.). It soon became 1134262685Sdelphijdifficult to manage this complexity and this gave birth to 'CURSES'. Curses is 1135262685Sdelphija pun on the name "cursor optimization". The Curses library forms a wrapper 1136262685Sdelphijover working with raw terminal codes, and provides highly flexible and 1137262685Sdelphijefficient API (Application Programming Interface). It provides functions to 1138262685Sdelphijmove the cursor, create windows, produce colors, play with mouse etc. The 1139262685Sdelphijapplication programs need not worry about the underlying terminal capabilities.</P 1140262685Sdelphij><P 1141262685Sdelphij>So what is NCURSES? NCURSES is a clone of the original System V Release 4.0 1142262685Sdelphij(SVr4) curses. It is a freely distributable library, fully compatible with 1143262685Sdelphijolder version of curses. In short, it is a library of functions that manages 1144262685Sdelphijan application's display on character-cell terminals. In the remainder of the 1145262685Sdelphijdocument, the terms curses and ncurses are used interchangeably. </P 1146262685Sdelphij><P 1147262685Sdelphij>A detailed history of NCURSES can be found in the NEWS file from the source 1148262685Sdelphijdistribution. The current package is maintained by 1149262685Sdelphij<A 1150262685SdelphijHREF="mailto:dickey@his.com" 1151262685SdelphijTARGET="_top" 1152262685Sdelphij>Thomas Dickey</A 1153262685Sdelphij>. 1154262685SdelphijYou can contact the maintainers at <A 1155262685SdelphijHREF="mailto:bug-ncurses@gnu.org" 1156262685SdelphijTARGET="_top" 1157262685Sdelphij>bug-ncurses@gnu.org</A 1158262685Sdelphij>.</P 1159262685Sdelphij></DIV 1160262685Sdelphij><DIV 1161262685SdelphijCLASS="SECT2" 1162262685Sdelphij><HR><H3 1163262685SdelphijCLASS="SECT2" 1164262685Sdelphij><A 1165262685SdelphijNAME="WHATCANWEDO" 1166262685Sdelphij>1.2. What we can do with NCURSES</A 1167262685Sdelphij></H3 1168262685Sdelphij><P 1169262685Sdelphij>NCURSES not only creates a wrapper over terminal capabilities, but also gives a 1170262685Sdelphijrobust framework to create nice looking UI (User Interface)s in text mode. It 1171262685Sdelphijprovides functions to create windows etc. Its sister libraries panel, menu and 1172262685Sdelphijform provide an extension to the basic curses library. These libraries usually 1173262685Sdelphijcome along with curses. One can create applications that contain multiple 1174262685Sdelphijwindows, menus, panels and forms. Windows can be managed independently, can 1175262685Sdelphijprovide 'scrollability' and even can be hidden.</P 1176262685Sdelphij><P 1177262685Sdelphij> 1178262685SdelphijMenus provide the user with an easy command selection option. Forms allow the 1179262685Sdelphijcreation of easy-to-use data entry and display windows. Panels extend the 1180262685Sdelphijcapabilities of ncurses to deal with overlapping and stacked windows.</P 1181262685Sdelphij><P 1182262685Sdelphij>These are just some of the basic things we can do with ncurses. As we move 1183262685Sdelphijalong, We will see all the capabilities of these libraries. </P 1184262685Sdelphij></DIV 1185262685Sdelphij><DIV 1186262685SdelphijCLASS="SECT2" 1187262685Sdelphij><HR><H3 1188262685SdelphijCLASS="SECT2" 1189262685Sdelphij><A 1190262685SdelphijNAME="WHERETOGETIT" 1191262685Sdelphij>1.3. Where to get it</A 1192262685Sdelphij></H3 1193262685Sdelphij><P 1194262685Sdelphij>All right, now that you know what you can do with ncurses, you must be rearing 1195262685Sdelphijto get started. NCURSES is usually shipped with your installation. In case 1196262685Sdelphijyou don't have the library or want to compile it on your own, read on.</P 1197262685Sdelphij><P 1198262685Sdelphij><SPAN 1199262685SdelphijCLASS="emphasis" 1200262685Sdelphij><I 1201262685SdelphijCLASS="EMPHASIS" 1202262685Sdelphij>Compiling the package</I 1203262685Sdelphij></SPAN 1204262685Sdelphij> </P 1205262685Sdelphij><P 1206262685Sdelphij>NCURSES can be obtained from <A 1207262685SdelphijHREF="ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz" 1208262685SdelphijTARGET="_top" 1209262685Sdelphij>ftp://ftp.gnu.org/pub/gnu/ncurses/ncurses.tar.gz</A 1210262685Sdelphij> or any of the ftp 1211262685Sdelphijsites mentioned in <A 1212262685SdelphijHREF="http://www.gnu.org/order/ftp.html" 1213262685SdelphijTARGET="_top" 1214262685Sdelphij>http://www.gnu.org/order/ftp.html</A 1215262685Sdelphij>. </P 1216262685Sdelphij><P 1217262685Sdelphij>Read the README and INSTALL files for details on to how to install it. It 1218262685Sdelphijusually involves the following operations.</P 1219262685Sdelphij><PRE 1220262685SdelphijCLASS="PROGRAMLISTING" 1221262685Sdelphij> tar zxvf ncurses<version>.tar.gz # unzip and untar the archive 1222166124Srafan cd ncurses<version> # cd to the directory 1223166124Srafan ./configure # configure the build according to your 1224166124Srafan # environment 1225166124Srafan make # make it 1226166124Srafan su root # become root 1227262685Sdelphij make install # install it</PRE 1228262685Sdelphij><P 1229262685Sdelphij><SPAN 1230262685SdelphijCLASS="emphasis" 1231262685Sdelphij><I 1232262685SdelphijCLASS="EMPHASIS" 1233262685Sdelphij>Using the RPM </I 1234262685Sdelphij></SPAN 1235262685Sdelphij></P 1236262685Sdelphij><P 1237262685Sdelphij>NCURSES RPM can be found and downloaded from <A 1238262685SdelphijHREF="http://rpmfind.net" 1239262685SdelphijTARGET="_top" 1240262685Sdelphij>http://rpmfind.net </A 1241262685Sdelphij>. The RPM can be installed with the following 1242262685Sdelphijcommand after becoming root.</P 1243262685Sdelphij><PRE 1244262685SdelphijCLASS="PROGRAMLISTING" 1245262685Sdelphij> rpm -i <downloaded rpm></PRE 1246262685Sdelphij></DIV 1247262685Sdelphij><DIV 1248262685SdelphijCLASS="SECT2" 1249262685Sdelphij><HR><H3 1250262685SdelphijCLASS="SECT2" 1251262685Sdelphij><A 1252262685SdelphijNAME="PURPOSE" 1253262685Sdelphij>1.4. Purpose/Scope of the document</A 1254262685Sdelphij></H3 1255262685Sdelphij><P 1256262685Sdelphij>This document is intended to be a "All in One" guide for programming with 1257262685Sdelphijncurses and its sister libraries. We graduate from a simple "Hello World" 1258262685Sdelphijprogram to more complex form manipulation. No prior experience in ncurses is 1259262685Sdelphijassumed. The writing is informal, but a lot of detail is provided for 1260262685Sdelphijeach of the examples.</P 1261262685Sdelphij></DIV 1262262685Sdelphij><DIV 1263262685SdelphijCLASS="SECT2" 1264262685Sdelphij><HR><H3 1265262685SdelphijCLASS="SECT2" 1266262685Sdelphij><A 1267262685SdelphijNAME="ABOUTPROGRAMS" 1268262685Sdelphij>1.5. About the Programs</A 1269262685Sdelphij></H3 1270262685Sdelphij><P 1271262685Sdelphij>All the programs in the document are available in zipped form 1272262685Sdelphij<A 1273262685SdelphijHREF="http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs.tar.gz" 1274262685SdelphijTARGET="_top" 1275262685Sdelphij>here</A 1276262685Sdelphij>. Unzip and untar it. The directory structure looks like this.</P 1277262685Sdelphij><PRE 1278262685SdelphijCLASS="PROGRAMLISTING" 1279262685Sdelphij>ncurses 1280166124Srafan | 1281166124Srafan |----> JustForFun -- just for fun programs 1282166124Srafan |----> basics -- basic programs 1283166124Srafan |----> demo -- output files go into this directory after make 1284166124Srafan | | 1285166124Srafan | |----> exe -- exe files of all example programs 1286166124Srafan |----> forms -- programs related to form library 1287166124Srafan |----> menus -- programs related to menus library 1288166124Srafan |----> panels -- programs related to panels library 1289166124Srafan |----> perl -- perl equivalents of the examples (contributed 1290166124Srafan | by Anuradha Ratnaweera) 1291166124Srafan |----> Makefile -- the top level Makefile 1292166124Srafan |----> README -- the top level README file. contains instructions 1293262685Sdelphij |----> COPYING -- copyright notice</PRE 1294262685Sdelphij><P 1295262685Sdelphij>The individual directories contain the following files.</P 1296262685Sdelphij><PRE 1297262685SdelphijCLASS="PROGRAMLISTING" 1298262685Sdelphij>Description of files in each directory 1299166124Srafan-------------------------------------- 1300166124SrafanJustForFun 1301166124Srafan | 1302166124Srafan |----> hanoi.c -- The Towers of Hanoi Solver 1303166124Srafan |----> life.c -- The Game of Life demo 1304166124Srafan |----> magic.c -- An Odd Order Magic Square builder 1305166124Srafan |----> queens.c -- The famous N-Queens Solver 1306166124Srafan |----> shuffle.c -- A fun game, if you have time to kill 1307166124Srafan |----> tt.c -- A very trivial typing tutor 1308166124Srafan 1309166124Srafan basics 1310166124Srafan | 1311166124Srafan |----> acs_vars.c -- ACS_ variables example 1312166124Srafan |----> hello_world.c -- Simple "Hello World" Program 1313166124Srafan |----> init_func_example.c -- Initialization functions example 1314166124Srafan |----> key_code.c -- Shows the scan code of the key pressed 1315166124Srafan |----> mouse_menu.c -- A menu accessible by mouse 1316166124Srafan |----> other_border.c -- Shows usage of other border functions apa 1317166124Srafan | -- rt from box() 1318166124Srafan |----> printw_example.c -- A very simple printw() example 1319166124Srafan |----> scanw_example.c -- A very simple getstr() example 1320166124Srafan |----> simple_attr.c -- A program that can print a c file with 1321166124Srafan | -- comments in attribute 1322166124Srafan |----> simple_color.c -- A simple example demonstrating colors 1323166124Srafan |----> simple_key.c -- A menu accessible with keyboard UP, DOWN 1324166124Srafan | -- arrows 1325166124Srafan |----> temp_leave.c -- Demonstrates temporarily leaving curses mode 1326166124Srafan |----> win_border.c -- Shows Creation of windows and borders 1327166124Srafan |----> with_chgat.c -- chgat() usage example 1328166124Srafan 1329166124Srafan forms 1330166124Srafan | 1331166124Srafan |----> form_attrib.c -- Usage of field attributes 1332166124Srafan |----> form_options.c -- Usage of field options 1333166124Srafan |----> form_simple.c -- A simple form example 1334166124Srafan |----> form_win.c -- Demo of windows associated with forms 1335166124Srafan 1336166124Srafan menus 1337166124Srafan | 1338166124Srafan |----> menu_attrib.c -- Usage of menu attributes 1339166124Srafan |----> menu_item_data.c -- Usage of item_name() etc.. functions 1340166124Srafan |----> menu_multi_column.c -- Creates multi columnar menus 1341166124Srafan |----> menu_scroll.c -- Demonstrates scrolling capability of menus 1342166124Srafan |----> menu_simple.c -- A simple menu accessed by arrow keys 1343166124Srafan |----> menu_toggle.c -- Creates multi valued menus and explains 1344166124Srafan | -- REQ_TOGGLE_ITEM 1345166124Srafan |----> menu_userptr.c -- Usage of user pointer 1346166124Srafan |----> menu_win.c -- Demo of windows associated with menus 1347166124Srafan 1348166124Srafan panels 1349166124Srafan | 1350166124Srafan |----> panel_browse.c -- Panel browsing through tab. Usage of user 1351166124Srafan | -- pointer 1352166124Srafan |----> panel_hide.c -- Hiding and Un hiding of panels 1353166124Srafan |----> panel_resize.c -- Moving and resizing of panels 1354166124Srafan |----> panel_simple.c -- A simple panel example 1355166124Srafan 1356166124Srafan perl 1357262685Sdelphij |----> 01-10.pl -- Perl equivalents of first ten example programs</PRE 1358262685Sdelphij><P 1359262685Sdelphij>There is a top level Makefile included in the main directory. It builds all the 1360262685Sdelphijfiles and puts the ready-to-use exes in demo/exe directory. You can also 1361262685Sdelphijdo selective make by going into the corresponding directory. Each directory 1362262685Sdelphijcontains a README file explaining the purpose of each c file in the directory.</P 1363262685Sdelphij><P 1364262685Sdelphij>For every example, I have included path name for the file relative to the 1365262685Sdelphijexamples directory. </P 1366262685Sdelphij><P 1367262685Sdelphij> If you prefer browsing individual programs, point your browser to 1368262685Sdelphij<A 1369262685SdelphijHREF="http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/" 1370262685SdelphijTARGET="_top" 1371262685Sdelphij>http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/ncurses_programs/</A 1372262685Sdelphij></P 1373262685Sdelphij><P 1374262685Sdelphij>All the programs are released under the same license that is used by ncurses 1375262685Sdelphij(MIT-style). This gives you the ability to do pretty much anything other than 1376262685Sdelphijclaiming them as yours. Feel free to use them in your programs as appropriate.</P 1377262685Sdelphij></DIV 1378262685Sdelphij><DIV 1379262685SdelphijCLASS="SECT2" 1380262685Sdelphij><HR><H3 1381262685SdelphijCLASS="SECT2" 1382262685Sdelphij><A 1383262685SdelphijNAME="OTHERFORMATS" 1384262685Sdelphij>1.6. Other Formats of the document</A 1385262685Sdelphij></H3 1386262685Sdelphij><P 1387262685Sdelphij>This howto is also availabe in various other formats on the tldp.org site. 1388262685SdelphijHere are the links to other formats of this document.</P 1389262685Sdelphij><DIV 1390262685SdelphijCLASS="SECT3" 1391262685Sdelphij><HR><H4 1392262685SdelphijCLASS="SECT3" 1393262685Sdelphij><A 1394262685SdelphijNAME="LISTFORMATS" 1395262685Sdelphij>1.6.1. Readily available formats from tldp.org</A 1396262685Sdelphij></H4 1397262685Sdelphij><P 1398262685Sdelphij></P 1399262685Sdelphij><UL 1400262685Sdelphij><LI 1401262685Sdelphij><P 1402262685Sdelphij><A 1403262685SdelphijHREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/pdf/NCURSES-Programming-HOWTO.pdf" 1404262685SdelphijTARGET="_top" 1405262685Sdelphij>Acrobat PDF Format</A 1406262685Sdelphij></P 1407262685Sdelphij></LI 1408262685Sdelphij><LI 1409262685Sdelphij><P 1410262685Sdelphij><A 1411262685SdelphijHREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/ps/NCURSES-Programming-HOWTO.ps.gz" 1412262685SdelphijTARGET="_top" 1413262685Sdelphij>PostScript Format</A 1414262685Sdelphij></P 1415262685Sdelphij></LI 1416262685Sdelphij><LI 1417262685Sdelphij><P 1418262685Sdelphij><A 1419262685SdelphijHREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html/NCURSES-Programming-HOWTO-html.tar.gz" 1420262685SdelphijTARGET="_top" 1421262685Sdelphij>In Multiple HTML pages</A 1422262685Sdelphij></P 1423262685Sdelphij></LI 1424262685Sdelphij><LI 1425262685Sdelphij><P 1426262685Sdelphij><A 1427262685SdelphijHREF="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/NCURSES-Programming-HOWTO.html" 1428262685SdelphijTARGET="_top" 1429262685Sdelphij>In One big HTML format</A 1430262685Sdelphij></P 1431262685Sdelphij></LI 1432262685Sdelphij></UL 1433262685Sdelphij></DIV 1434262685Sdelphij><DIV 1435262685SdelphijCLASS="SECT3" 1436262685Sdelphij><HR><H4 1437262685SdelphijCLASS="SECT3" 1438262685Sdelphij><A 1439262685SdelphijNAME="BUILDSOURCE" 1440262685Sdelphij>1.6.2. Building from source</A 1441262685Sdelphij></H4 1442262685Sdelphij><P 1443262685Sdelphij>If above links are broken or if you want to experiment with sgml read on. 1444262685Sdelphij<PRE 1445262685SdelphijCLASS="PROGRAMLISTING" 1446262685Sdelphij> Get both the source and the tar,gzipped programs, available at 1447166124Srafan http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/ 1448166124Srafan NCURSES-HOWTO/NCURSES-Programming-HOWTO.sgml 1449166124Srafan http://cvsview.tldp.org/index.cgi/LDP/howto/docbook/ 1450166124Srafan NCURSES-HOWTO/ncurses_programs.tar.gz 1451166124Srafan 1452166124Srafan Unzip ncurses_programs.tar.gz with 1453166124Srafan tar zxvf ncurses_programs.tar.gz 1454166124Srafan 1455166124Srafan Use jade to create various formats. For example if you just want to create 1456166124Srafan the multiple html files, you would use 1457166124Srafan jade -t sgml -i html -d <path to docbook html stylesheet> 1458166124Srafan NCURSES-Programming-HOWTO.sgml 1459166124Srafan to get pdf, first create a single html file of the HOWTO with 1460166124Srafan jade -t sgml -i html -d <path to docbook html stylesheet> -V nochunks 1461166124Srafan NCURSES-Programming-HOWTO.sgml > NCURSES-ONE-BIG-FILE.html 1462166124Srafan then use htmldoc to get pdf file with 1463166124Srafan htmldoc --size universal -t pdf --firstpage p1 -f <output file name.pdf> 1464166124Srafan NCURSES-ONE-BIG-FILE.html 1465166124Srafan for ps, you would use 1466166124Srafan htmldoc --size universal -t ps --firstpage p1 -f <output file name.ps> 1467262685Sdelphij NCURSES-ONE-BIG-FILE.html</PRE 1468262685Sdelphij></P 1469262685Sdelphij><P 1470262685Sdelphij>See <A 1471262685SdelphijHREF="http://www.tldp.org/LDP/LDP-Author-Guide/" 1472262685SdelphijTARGET="_top" 1473262685Sdelphij>LDP Author guide</A 1474262685Sdelphij> for more details. If all else failes, mail me at 1475262685Sdelphij<A 1476262685SdelphijHREF="ppadala@gmail.com" 1477262685SdelphijTARGET="_top" 1478262685Sdelphij>ppadala@gmail.com</A 1479262685Sdelphij></P 1480262685Sdelphij></DIV 1481262685Sdelphij></DIV 1482262685Sdelphij><DIV 1483262685SdelphijCLASS="SECT2" 1484262685Sdelphij><HR><H3 1485262685SdelphijCLASS="SECT2" 1486262685Sdelphij><A 1487262685SdelphijNAME="CREDITS" 1488262685Sdelphij>1.7. Credits</A 1489262685Sdelphij></H3 1490262685Sdelphij><P 1491262685Sdelphij>I thank <A 1492262685SdelphijHREF="mailto:sharath_1@usa.net" 1493262685SdelphijTARGET="_top" 1494262685Sdelphij>Sharath</A 1495262685Sdelphij> and Emre Akbas for 1496262685Sdelphijhelping me with few sections. The introduction was initially written by sharath. 1497262685SdelphijI rewrote it with few excerpts taken from his initial work. Emre helped in 1498262685Sdelphijwriting printw and scanw sections.</P 1499262685Sdelphij><P 1500262685Sdelphij>Perl equivalents of the example programs are contributed by <A 1501262685SdelphijHREF="mailto:Aratnaweera@virtusa.com" 1502262685SdelphijTARGET="_top" 1503262685Sdelphij>Anuradha Ratnaweera</A 1504262685Sdelphij>. </P 1505262685Sdelphij><P 1506262685Sdelphij>Then comes <A 1507262685SdelphijHREF="mailto:parimi@ece.arizona.edu" 1508262685SdelphijTARGET="_top" 1509262685Sdelphij>Ravi Parimi</A 1510262685Sdelphij>, my 1511262685Sdelphijdearest friend, who has been on this project before even one line was written. 1512262685SdelphijHe constantly bombarded me with suggestions and patiently reviewed the whole 1513262685Sdelphijtext. He also checked each program on Linux and Solaris. </P 1514262685Sdelphij></DIV 1515262685Sdelphij><DIV 1516262685SdelphijCLASS="SECT2" 1517262685Sdelphij><HR><H3 1518262685SdelphijCLASS="SECT2" 1519262685Sdelphij><A 1520262685SdelphijNAME="WISHLIST" 1521262685Sdelphij>1.8. Wish List</A 1522262685Sdelphij></H3 1523262685Sdelphij><P 1524262685Sdelphij>This is the wish list, in the order of priority. If you have a wish or you want 1525262685Sdelphijto work on completing the wish, mail <A 1526262685SdelphijHREF="mailto:ppadala@gmail.com" 1527262685SdelphijTARGET="_top" 1528262685Sdelphij>me</A 1529262685Sdelphij>. </P 1530262685Sdelphij><P 1531262685Sdelphij></P 1532262685Sdelphij><UL 1533262685Sdelphij><LI 1534262685Sdelphij><P 1535262685Sdelphij>Add examples to last parts of forms section.</P 1536262685Sdelphij></LI 1537262685Sdelphij><LI 1538262685Sdelphij><P 1539262685Sdelphij>Prepare a Demo showing all the programs and allow the user to browse through 1540262685Sdelphijdescription of each program. Let the user compile and see the program in action. 1541262685SdelphijA dialog based interface is preferred.</P 1542262685Sdelphij></LI 1543262685Sdelphij><LI 1544262685Sdelphij><P 1545262685Sdelphij>Add debug info. _tracef, _tracemouse stuff.</P 1546262685Sdelphij></LI 1547262685Sdelphij><LI 1548262685Sdelphij><P 1549262685Sdelphij>Accessing termcap, terminfo using functions provided by ncurses 1550262685Sdelphijpackage.</P 1551262685Sdelphij></LI 1552262685Sdelphij><LI 1553262685Sdelphij><P 1554262685Sdelphij>Working on two terminals simultaneously.</P 1555262685Sdelphij></LI 1556262685Sdelphij><LI 1557262685Sdelphij><P 1558262685Sdelphij>Add more stuff to miscellaneous section.</P 1559262685Sdelphij></LI 1560262685Sdelphij></UL 1561262685Sdelphij></DIV 1562262685Sdelphij><DIV 1563262685SdelphijCLASS="SECT2" 1564262685Sdelphij><HR><H3 1565262685SdelphijCLASS="SECT2" 1566262685Sdelphij><A 1567262685SdelphijNAME="COPYRIGHT" 1568262685Sdelphij>1.9. Copyright</A 1569262685Sdelphij></H3 1570262685Sdelphij><P 1571262685Sdelphij>Copyright © 2001 by Pradeep Padala. </P 1572262685Sdelphij><P 1573262685Sdelphij>Permission is hereby granted, free of charge, to any person obtaining a copy 1574262685Sdelphijof this software and associated documentation files (the "Software"), to deal 1575262685Sdelphijin the Software without restriction, including without limitation the rights 1576262685Sdelphijto use, copy, modify, merge, publish, distribute, distribute with 1577262685Sdelphijmodifications, sublicense, and/or sell copies of the Software, and to permit 1578262685Sdelphijpersons to whom the Software is furnished to do so, subject to the following 1579262685Sdelphijconditions:</P 1580262685Sdelphij><P 1581262685Sdelphij>The above copyright notice and this permission notice shall be included in all 1582262685Sdelphijcopies or substantial portions of the Software.</P 1583262685Sdelphij><P 1584262685Sdelphij>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1585262685SdelphijIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1586262685SdelphijFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1587262685SdelphijABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 1588262685SdelphijWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 1589262685SdelphijIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</P 1590262685Sdelphij><P 1591262685Sdelphij>Except as contained in this notice, the name(s) of the above copyright holders 1592262685Sdelphijshall not be used in advertising or otherwise to promote the sale, use or 1593262685Sdelphijother dealings in this Software without prior written authorization. </P 1594262685Sdelphij></DIV 1595262685Sdelphij></DIV 1596262685Sdelphij><DIV 1597262685SdelphijCLASS="SECT1" 1598262685Sdelphij><HR><H2 1599262685SdelphijCLASS="SECT1" 1600262685Sdelphij><A 1601262685SdelphijNAME="HELLOWORLD" 1602262685Sdelphij>2. Hello World !!!</A 1603262685Sdelphij></H2 1604262685Sdelphij><P 1605262685Sdelphij>Welcome to the world of curses. Before we plunge into the library and look into 1606262685Sdelphijits various features, let's write a simple program and say 1607262685Sdelphijhello to the world. </P 1608262685Sdelphij><DIV 1609262685SdelphijCLASS="SECT2" 1610262685Sdelphij><HR><H3 1611262685SdelphijCLASS="SECT2" 1612262685Sdelphij><A 1613262685SdelphijNAME="COMPILECURSES" 1614262685Sdelphij>2.1. Compiling With the NCURSES Library</A 1615262685Sdelphij></H3 1616262685Sdelphij><P 1617262685Sdelphij>To use ncurses library functions, you have to include ncurses.h in your 1618262685Sdelphijprograms. To link the 1619262685Sdelphijprogram with ncurses the flag -lncurses should be added.</P 1620262685Sdelphij><PRE 1621262685SdelphijCLASS="PROGRAMLISTING" 1622262685Sdelphij> #include <ncurses.h> 1623166124Srafan . 1624166124Srafan . 1625166124Srafan . 1626166124Srafan 1627262685Sdelphij compile and link: gcc <program file> -lncurses</PRE 1628262685Sdelphij><DIV 1629262685SdelphijCLASS="EXAMPLE" 1630262685Sdelphij><A 1631262685SdelphijNAME="BHW" 1632262685Sdelphij></A 1633262685Sdelphij><P 1634262685Sdelphij><B 1635262685Sdelphij>Example 1. The Hello World !!! Program </B 1636262685Sdelphij></P 1637262685Sdelphij><PRE 1638262685SdelphijCLASS="PROGRAMLISTING" 1639262685Sdelphij><SPAN 1640262685SdelphijCLASS="INLINEMEDIAOBJECT" 1641262685Sdelphij>#include <ncurses.h> 1642166124Srafan 1643166124Srafanint main() 1644262685Sdelphij{ 1645262685Sdelphij initscr(); /* Start curses mode */ 1646262685Sdelphij printw("Hello World !!!"); /* Print Hello World */ 1647262685Sdelphij refresh(); /* Print it on to the real screen */ 1648262685Sdelphij getch(); /* Wait for user input */ 1649262685Sdelphij endwin(); /* End curses mode */ 1650166124Srafan 1651262685Sdelphij return 0; 1652262685Sdelphij}</SPAN 1653262685Sdelphij></PRE 1654262685Sdelphij></DIV 1655262685Sdelphij></DIV 1656262685Sdelphij><DIV 1657262685SdelphijCLASS="SECT2" 1658262685Sdelphij><HR><H3 1659262685SdelphijCLASS="SECT2" 1660262685Sdelphij><A 1661262685SdelphijNAME="DISSECTION" 1662262685Sdelphij>2.2. Dissection</A 1663262685Sdelphij></H3 1664262685Sdelphij><P 1665262685Sdelphij> 1666262685SdelphijThe above program prints "Hello World !!!" to the screen and exits. This 1667262685Sdelphijprogram shows how to initialize curses and do screen manipulation and 1668262685Sdelphijend curses mode. Let's dissect it line by line. </P 1669262685Sdelphij><DIV 1670262685SdelphijCLASS="SECT3" 1671262685Sdelphij><HR><H4 1672262685SdelphijCLASS="SECT3" 1673262685Sdelphij><A 1674262685SdelphijNAME="ABOUT-INITSCR" 1675262685Sdelphij>2.2.1. About initscr()</A 1676262685Sdelphij></H4 1677262685Sdelphij><P 1678262685Sdelphij>The function initscr() initializes the terminal in curses mode. In some 1679262685Sdelphijimplementations, it clears the screen and presents a blank screen. To do any 1680262685Sdelphijscreen manipulation using curses package this has to be called first. This 1681262685Sdelphijfunction initializes the curses system and allocates memory for our present 1682262685Sdelphijwindow (called <TT 1683262685SdelphijCLASS="LITERAL" 1684262685Sdelphij>stdscr</TT 1685262685Sdelphij>) and some other data-structures. Under extreme 1686262685Sdelphijcases this function might fail due to insufficient memory to allocate memory 1687262685Sdelphijfor curses library's data structures. </P 1688262685Sdelphij><P 1689262685Sdelphij> 1690262685SdelphijAfter this is done, we can do a variety of initializations to customize 1691262685Sdelphijour curses settings. These details will be explained <A 1692262685SdelphijHREF="#INIT" 1693262685Sdelphij>later </A 1694262685Sdelphij>.</P 1695262685Sdelphij></DIV 1696262685Sdelphij><DIV 1697262685SdelphijCLASS="SECT3" 1698262685Sdelphij><HR><H4 1699262685SdelphijCLASS="SECT3" 1700262685Sdelphij><A 1701262685SdelphijNAME="MYST-REFRESH" 1702262685Sdelphij>2.2.2. The mysterious refresh()</A 1703262685Sdelphij></H4 1704262685Sdelphij><P 1705262685Sdelphij>The next line printw prints the string "Hello World !!!" on to the screen. This 1706262685Sdelphijfunction is analogous to normal printf in all respects except that it prints 1707262685Sdelphijthe data on a window called stdscr at the current (y,x) co-ordinates. Since our 1708262685Sdelphijpresent co-ordinates are at 0,0 the string is printed at the left hand corner 1709262685Sdelphijof the window.</P 1710262685Sdelphij><P 1711262685Sdelphij>This brings us to that mysterious refresh(). Well, when we called printw 1712262685Sdelphijthe data is actually written to an imaginary window, which is not updated 1713262685Sdelphijon the screen yet. The job of printw is to update a few flags 1714262685Sdelphijand data structures and write the data to a buffer corresponding to stdscr. 1715262685SdelphijIn order to show it on the screen, we need to call refresh() and tell the 1716262685Sdelphijcurses system to dump the contents on the screen.</P 1717262685Sdelphij><P 1718262685Sdelphij>The philosophy behind all this is to allow the programmer to do multiple updates 1719262685Sdelphijon the imaginary screen or windows and do a refresh once all his screen update 1720262685Sdelphijis done. refresh() checks the window and updates only the portion which has been 1721262685Sdelphijchanged. This improves performance and offers greater flexibility too. But, it is 1722262685Sdelphijsometimes frustrating to beginners. A common mistake committed by beginners is 1723262685Sdelphijto forget to call refresh() after they did some update through printw() class of 1724262685Sdelphijfunctions. I still forget to add it sometimes :-) </P 1725262685Sdelphij></DIV 1726262685Sdelphij><DIV 1727262685SdelphijCLASS="SECT3" 1728262685Sdelphij><HR><H4 1729262685SdelphijCLASS="SECT3" 1730262685Sdelphij><A 1731262685SdelphijNAME="ABOUT-ENDWIN" 1732262685Sdelphij>2.2.3. About endwin()</A 1733262685Sdelphij></H4 1734262685Sdelphij><P 1735262685Sdelphij>And finally don't forget to end the curses mode. Otherwise your terminal might 1736262685Sdelphijbehave strangely after the program quits. endwin() frees the memory taken by 1737262685Sdelphijcurses sub-system and its data structures and puts the terminal in normal 1738262685Sdelphijmode. This function must be called after you are done with the curses mode. </P 1739262685Sdelphij></DIV 1740262685Sdelphij></DIV 1741262685Sdelphij></DIV 1742262685Sdelphij><DIV 1743262685SdelphijCLASS="SECT1" 1744262685Sdelphij><HR><H2 1745262685SdelphijCLASS="SECT1" 1746262685Sdelphij><A 1747262685SdelphijNAME="GORY" 1748262685Sdelphij>3. The Gory Details</A 1749262685Sdelphij></H2 1750262685Sdelphij><P 1751262685Sdelphij>Now that we have seen how to write a simple curses program let's get into the 1752262685Sdelphijdetails. There are many functions that help customize what you see on screen and 1753262685Sdelphijmany features which can be put to full use. </P 1754262685Sdelphij><P 1755262685Sdelphij>Here we go...</P 1756262685Sdelphij></DIV 1757262685Sdelphij><DIV 1758262685SdelphijCLASS="SECT1" 1759262685Sdelphij><HR><H2 1760262685SdelphijCLASS="SECT1" 1761262685Sdelphij><A 1762262685SdelphijNAME="INIT" 1763262685Sdelphij>4. Initialization</A 1764262685Sdelphij></H2 1765262685Sdelphij><P 1766262685Sdelphij>We now know that to initialize curses system the function initscr() has to be 1767262685Sdelphijcalled. There are functions which can be called after this initialization to 1768262685Sdelphijcustomize our curses session. We may ask the curses system to set the terminal 1769262685Sdelphijin raw mode or initialize color or initialize the mouse etc.. Let's discuss some 1770262685Sdelphijof the functions that are normally called immediately after initscr();</P 1771262685Sdelphij><DIV 1772262685SdelphijCLASS="SECT2" 1773262685Sdelphij><HR><H3 1774262685SdelphijCLASS="SECT2" 1775262685Sdelphij><A 1776262685SdelphijNAME="ABOUTINIT" 1777262685Sdelphij>4.1. Initialization functions</A 1778262685Sdelphij></H3 1779262685Sdelphij><P 1780262685Sdelphij> </P 1781262685Sdelphij></DIV 1782262685Sdelphij><DIV 1783262685SdelphijCLASS="SECT2" 1784262685Sdelphij><HR><H3 1785262685SdelphijCLASS="SECT2" 1786262685Sdelphij><A 1787262685SdelphijNAME="RAWCBREAK" 1788262685Sdelphij>4.2. raw() and cbreak()</A 1789262685Sdelphij></H3 1790262685Sdelphij><P 1791262685Sdelphij>Normally the terminal driver buffers the characters a user types until a new 1792262685Sdelphijline or carriage return is encountered. But most programs require that the 1793262685Sdelphijcharacters be available as soon as the user types them. The above two functions 1794262685Sdelphijare used to disable line buffering. The difference between these two functions 1795262685Sdelphijis in the way control characters like suspend (CTRL-Z), interrupt and quit 1796262685Sdelphij(CTRL-C) are passed to the program. In the raw() mode these characters are 1797262685Sdelphijdirectly passed to the program without generating a signal. In the 1798262685Sdelphij<TT 1799262685SdelphijCLASS="LITERAL" 1800262685Sdelphij>cbreak()</TT 1801262685Sdelphij> mode these control characters are 1802262685Sdelphijinterpreted as any other character by the terminal driver. I personally prefer 1803262685Sdelphijto use raw() as I can exercise greater control over what the user does.</P 1804262685Sdelphij></DIV 1805262685Sdelphij><DIV 1806262685SdelphijCLASS="SECT2" 1807262685Sdelphij><HR><H3 1808262685SdelphijCLASS="SECT2" 1809262685Sdelphij><A 1810262685SdelphijNAME="ECHONOECHO" 1811262685Sdelphij>4.3. echo() and noecho()</A 1812262685Sdelphij></H3 1813262685Sdelphij><P 1814262685Sdelphij> 1815262685SdelphijThese functions control the echoing of characters typed by the user to the 1816262685Sdelphijterminal. <TT 1817262685SdelphijCLASS="LITERAL" 1818262685Sdelphij>noecho()</TT 1819262685Sdelphij> switches off echoing. The 1820262685Sdelphijreason you might want to do this is to gain more control over echoing or to 1821262685Sdelphijsuppress unnecessary echoing while taking input from the user through the 1822262685Sdelphijgetch() etc. functions. Most of the interactive programs call 1823262685Sdelphij<TT 1824262685SdelphijCLASS="LITERAL" 1825262685Sdelphij>noecho()</TT 1826262685Sdelphij> at initialization and do the echoing 1827262685Sdelphijof characters in a controlled manner. It gives the programmer the flexibility 1828262685Sdelphijof echoing characters at any place in the window without updating current (y,x) 1829262685Sdelphijco-ordinates. </P 1830262685Sdelphij></DIV 1831262685Sdelphij><DIV 1832262685SdelphijCLASS="SECT2" 1833262685Sdelphij><HR><H3 1834262685SdelphijCLASS="SECT2" 1835262685Sdelphij><A 1836262685SdelphijNAME="KEYPAD" 1837262685Sdelphij>4.4. keypad()</A 1838262685Sdelphij></H3 1839262685Sdelphij><P 1840262685Sdelphij>This is my favorite initialization function. It enables the reading of function 1841262685Sdelphijkeys like F1, F2, arrow keys etc. Almost every interactive program enables this, 1842262685Sdelphijas arrow keys are a major part of any User Interface. Do 1843262685Sdelphij<TT 1844262685SdelphijCLASS="LITERAL" 1845262685Sdelphij>keypad(stdscr, TRUE) </TT 1846262685Sdelphij> to enable this feature 1847262685Sdelphijfor the regular screen (stdscr). You will learn more about key management in 1848262685Sdelphijlater sections of this document.</P 1849262685Sdelphij></DIV 1850262685Sdelphij><DIV 1851262685SdelphijCLASS="SECT2" 1852262685Sdelphij><HR><H3 1853262685SdelphijCLASS="SECT2" 1854262685Sdelphij><A 1855262685SdelphijNAME="HALFDELAY" 1856262685Sdelphij>4.5. halfdelay()</A 1857262685Sdelphij></H3 1858262685Sdelphij><P 1859262685Sdelphij>This function, though not used very often, is a useful one at times. 1860262685Sdelphijhalfdelay()is called to enable the half-delay mode, which is similar to the 1861262685Sdelphijcbreak() mode in that characters typed are immediately available to program. 1862262685SdelphijHowever, it waits for 'X' tenths of a second for input and then returns ERR, if 1863262685Sdelphijno input is available. 'X' is the timeout value passed to the function 1864262685Sdelphijhalfdelay(). This function is useful when you want to ask the user for input, 1865262685Sdelphijand if he doesn't respond with in certain time, we can do some thing else. One 1866262685Sdelphijpossible example is a timeout at the password prompt. </P 1867262685Sdelphij></DIV 1868262685Sdelphij><DIV 1869262685SdelphijCLASS="SECT2" 1870262685Sdelphij><HR><H3 1871262685SdelphijCLASS="SECT2" 1872262685Sdelphij><A 1873262685SdelphijNAME="MISCINIT" 1874262685Sdelphij>4.6. Miscellaneous Initialization functions</A 1875262685Sdelphij></H3 1876262685Sdelphij><P 1877262685Sdelphij>There are few more functions which are called at initialization to 1878262685Sdelphijcustomize curses behavior. They are not used as extensively as those mentioned 1879262685Sdelphijabove. Some of them are explained where appropriate.</P 1880262685Sdelphij></DIV 1881262685Sdelphij><DIV 1882262685SdelphijCLASS="SECT2" 1883262685Sdelphij><HR><H3 1884262685SdelphijCLASS="SECT2" 1885262685Sdelphij><A 1886262685SdelphijNAME="INITEX" 1887262685Sdelphij>4.7. An Example</A 1888262685Sdelphij></H3 1889262685Sdelphij><P 1890262685Sdelphij>Let's write a program which will clarify the usage of these functions.</P 1891262685Sdelphij><DIV 1892262685SdelphijCLASS="EXAMPLE" 1893262685Sdelphij><A 1894262685SdelphijNAME="BINFU" 1895262685Sdelphij></A 1896262685Sdelphij><P 1897262685Sdelphij><B 1898262685Sdelphij>Example 2. Initialization Function Usage example </B 1899262685Sdelphij></P 1900262685Sdelphij><PRE 1901262685SdelphijCLASS="PROGRAMLISTING" 1902262685Sdelphij><SPAN 1903262685SdelphijCLASS="INLINEMEDIAOBJECT" 1904262685Sdelphij>#include <ncurses.h> 1905166124Srafan 1906166124Srafanint main() 1907262685Sdelphij{ int ch; 1908166124Srafan 1909262685Sdelphij initscr(); /* Start curses mode */ 1910262685Sdelphij raw(); /* Line buffering disabled */ 1911262685Sdelphij keypad(stdscr, TRUE); /* We get F1, F2 etc.. */ 1912262685Sdelphij noecho(); /* Don't echo() while we do getch */ 1913166124Srafan 1914262685Sdelphij printw("Type any character to see it in bold\n"); 1915262685Sdelphij ch = getch(); /* If raw() hadn't been called 1916262685Sdelphij * we have to press enter before it 1917262685Sdelphij * gets to the program */ 1918262685Sdelphij if(ch == KEY_F(1)) /* Without keypad enabled this will */ 1919262685Sdelphij printw("F1 Key pressed");/* not get to us either */ 1920262685Sdelphij /* Without noecho() some ugly escape 1921262685Sdelphij * charachters might have been printed 1922262685Sdelphij * on screen */ 1923262685Sdelphij else 1924262685Sdelphij { printw("The pressed key is "); 1925262685Sdelphij attron(A_BOLD); 1926262685Sdelphij printw("%c", ch); 1927262685Sdelphij attroff(A_BOLD); 1928262685Sdelphij } 1929262685Sdelphij refresh(); /* Print it on to the real screen */ 1930262685Sdelphij getch(); /* Wait for user input */ 1931262685Sdelphij endwin(); /* End curses mode */ 1932166124Srafan 1933262685Sdelphij return 0; 1934262685Sdelphij}</SPAN 1935262685Sdelphij></PRE 1936262685Sdelphij></DIV 1937262685Sdelphij><P 1938262685Sdelphij>This program is self-explanatory. But I used functions which aren't explained 1939262685Sdelphijyet. The function <TT 1940262685SdelphijCLASS="LITERAL" 1941262685Sdelphij>getch()</TT 1942262685Sdelphij> is used to get a 1943262685Sdelphijcharacter from user. It is equivalent to normal 1944262685Sdelphij<TT 1945262685SdelphijCLASS="LITERAL" 1946262685Sdelphij>getchar()</TT 1947262685Sdelphij> except that we can disable the line 1948262685Sdelphijbuffering to avoid <enter> after input. Look for more about 1949262685Sdelphij<TT 1950262685SdelphijCLASS="LITERAL" 1951262685Sdelphij>getch()</TT 1952262685Sdelphij>and reading keys in the <A 1953262685SdelphijHREF="#KEYS" 1954262685Sdelphij> key management section </A 1955262685Sdelphij>. The functions attron and attroff 1956262685Sdelphijare used to switch some attributes on and off respectively. In the example I 1957262685Sdelphijused them to print the character in bold. These functions are explained in detail 1958262685Sdelphijlater.</P 1959262685Sdelphij></DIV 1960262685Sdelphij></DIV 1961262685Sdelphij><DIV 1962262685SdelphijCLASS="SECT1" 1963262685Sdelphij><HR><H2 1964262685SdelphijCLASS="SECT1" 1965262685Sdelphij><A 1966262685SdelphijNAME="AWORDWINDOWS" 1967262685Sdelphij>5. A Word about Windows</A 1968262685Sdelphij></H2 1969262685Sdelphij><P 1970262685Sdelphij> 1971262685SdelphijBefore we plunge into the myriad ncurses functions, let me clear few things 1972262685Sdelphijabout windows. Windows are explained in detail in following <A 1973262685SdelphijHREF="#WINDOWS" 1974262685Sdelphij> sections </A 1975262685Sdelphij></P 1976262685Sdelphij><P 1977262685Sdelphij>A Window is an imaginary screen defined by curses system. A window does not mean 1978262685Sdelphija bordered window which you usually see on Win9X platforms. When curses is 1979262685Sdelphijinitialized, it creates a default window named 1980262685Sdelphij<TT 1981262685SdelphijCLASS="LITERAL" 1982262685Sdelphij>stdscr</TT 1983262685Sdelphij> which represents your 80x25 (or the size 1984262685Sdelphijof window in which you are running) screen. If you are doing simple tasks like 1985262685Sdelphijprinting few strings, reading input etc., you can safely use this single window 1986262685Sdelphijfor all of your purposes. You can also create windows and call functions which 1987262685Sdelphijexplicitly work on the specified window.</P 1988262685Sdelphij><P 1989262685Sdelphij>For example, if you call</P 1990262685Sdelphij><PRE 1991262685SdelphijCLASS="PROGRAMLISTING" 1992262685Sdelphij> printw("Hi There !!!"); 1993262685Sdelphij refresh();</PRE 1994262685Sdelphij><P 1995262685Sdelphij>It prints the string on stdscr at the present cursor position. Similarly the 1996262685Sdelphijcall to refresh(), works on stdscr only. </P 1997262685Sdelphij><P 1998262685Sdelphij>Say you have created <A 1999262685SdelphijHREF="#WINDOWS" 2000262685Sdelphij>windows</A 2001262685Sdelphij> then you have to 2002262685Sdelphijcall a function with a 'w' added to the usual function.</P 2003262685Sdelphij><PRE 2004262685SdelphijCLASS="PROGRAMLISTING" 2005262685Sdelphij> wprintw(win, "Hi There !!!"); 2006262685Sdelphij wrefresh(win);</PRE 2007262685Sdelphij><P 2008262685Sdelphij>As you will see in the rest of the document, naming of functions follow the 2009262685Sdelphijsame convention. For each function there usually are three more functions.</P 2010262685Sdelphij><PRE 2011262685SdelphijCLASS="PROGRAMLISTING" 2012262685Sdelphij> printw(string); /* Print on stdscr at present cursor position */ 2013166124Srafan mvprintw(y, x, string);/* Move to (y, x) then print string */ 2014166124Srafan wprintw(win, string); /* Print on window win at present cursor position */ 2015166124Srafan /* in the window */ 2016166124Srafan mvwprintw(win, y, x, string); /* Move to (y, x) relative to window */ 2017262685Sdelphij /* co-ordinates and then print */</PRE 2018262685Sdelphij><P 2019262685Sdelphij>Usually the w-less functions are macros which expand to corresponding w-function 2020262685Sdelphijwith stdscr as the window parameter.</P 2021262685Sdelphij></DIV 2022262685Sdelphij><DIV 2023262685SdelphijCLASS="SECT1" 2024262685Sdelphij><HR><H2 2025262685SdelphijCLASS="SECT1" 2026262685Sdelphij><A 2027262685SdelphijNAME="PRINTW" 2028262685Sdelphij>6. Output functions</A 2029262685Sdelphij></H2 2030262685Sdelphij><P 2031262685Sdelphij>I guess you can't wait any more to see some action. Back to our odyssey of 2032262685Sdelphijcurses functions. Now that curses is initialized, let's interact with 2033262685Sdelphijworld.</P 2034262685Sdelphij><P 2035262685Sdelphij>There are three classes of functions which you can use to do output on screen. 2036262685Sdelphij<P 2037262685Sdelphij></P 2038262685Sdelphij><OL 2039262685SdelphijTYPE="1" 2040262685Sdelphij><LI 2041262685Sdelphij><P 2042262685Sdelphij>addch() class: Print single character with attributes </P 2043262685Sdelphij></LI 2044262685Sdelphij><LI 2045262685Sdelphij><P 2046262685Sdelphij>printw() class: Print formatted output similar to printf()</P 2047262685Sdelphij></LI 2048262685Sdelphij><LI 2049262685Sdelphij><P 2050262685Sdelphij>addstr() class: Print strings</P 2051262685Sdelphij></LI 2052262685Sdelphij></OL 2053262685Sdelphij></P 2054262685Sdelphij><P 2055262685Sdelphij>These functions can be used interchangeably and it's a matter of style as to 2056262685Sdelphijwhich class is used. Let's see each one in detail.</P 2057262685Sdelphij><DIV 2058262685SdelphijCLASS="SECT2" 2059262685Sdelphij><HR><H3 2060262685SdelphijCLASS="SECT2" 2061262685Sdelphij><A 2062262685SdelphijNAME="ADDCHCLASS" 2063262685Sdelphij>6.1. addch() class of functions</A 2064262685Sdelphij></H3 2065262685Sdelphij><P 2066262685Sdelphij>These functions put a single character into the current cursor location and 2067262685Sdelphijadvance the position of the cursor. You can give the character to be printed but 2068262685Sdelphijthey usually are used to print a character with some attributes. Attributes are 2069262685Sdelphijexplained in detail in later <A 2070262685SdelphijHREF="#ATTRIB" 2071262685Sdelphij> sections </A 2072262685Sdelphij> of the 2073262685Sdelphijdocument. If a character is associated with an attribute(bold, reverse video 2074262685Sdelphijetc.), when curses prints the character, it is printed in that attribute.</P 2075262685Sdelphij><P 2076262685Sdelphij>In order to combine a character with some attributes, you have two options:</P 2077262685Sdelphij><P 2078262685Sdelphij></P 2079262685Sdelphij><UL 2080262685Sdelphij><LI 2081262685Sdelphij><P 2082262685Sdelphij>By OR'ing a single character with the desired attribute macros. These attribute 2083262685Sdelphijmacros could be found in the header file 2084262685Sdelphij<TT 2085262685SdelphijCLASS="LITERAL" 2086262685Sdelphij>ncurses.h</TT 2087262685Sdelphij>. For example, you want to print a 2088262685Sdelphijcharacter ch(of type char) bold and underlined, you would call addch() as below. 2089262685Sdelphij<PRE 2090262685SdelphijCLASS="PROGRAMLISTING" 2091262685Sdelphij> addch(ch | A_BOLD | A_UNDERLINE);</PRE 2092262685Sdelphij></P 2093262685Sdelphij></LI 2094262685Sdelphij><LI 2095262685Sdelphij><P 2096262685Sdelphij>By using functions like <TT 2097262685SdelphijCLASS="LITERAL" 2098262685Sdelphij>attrset(),attron(),attroff()</TT 2099262685Sdelphij>. These functions are explained in the <A 2100262685SdelphijHREF="#ATTRIB" 2101262685Sdelphij>Attributes</A 2102262685Sdelphij> section. Briefly, they manipulate the current attributes of 2103262685Sdelphijthe given window. Once set, the character printed in the window are associated 2104262685Sdelphijwith the attributes until it is turned off.</P 2105262685Sdelphij></LI 2106262685Sdelphij></UL 2107262685Sdelphij><P 2108262685Sdelphij>Additionally, <TT 2109262685SdelphijCLASS="LITERAL" 2110262685Sdelphij>curses</TT 2111262685Sdelphij> provides some special 2112262685Sdelphijcharacters for character-based graphics. You can draw tables, horizontal or 2113262685Sdelphijvertical lines, etc. You can find all avaliable characters in the header file 2114262685Sdelphij<TT 2115262685SdelphijCLASS="LITERAL" 2116262685Sdelphij>ncurses.h</TT 2117262685Sdelphij>. Try looking for macros beginning 2118262685Sdelphijwith <TT 2119262685SdelphijCLASS="LITERAL" 2120262685Sdelphij>ACS_</TT 2121262685Sdelphij> in this file. </P 2122262685Sdelphij></DIV 2123262685Sdelphij><DIV 2124262685SdelphijCLASS="SECT2" 2125262685Sdelphij><HR><H3 2126262685SdelphijCLASS="SECT2" 2127262685Sdelphij><A 2128262685SdelphijNAME="AEN298" 2129262685Sdelphij>6.2. mvaddch(), waddch() and mvwaddch()</A 2130262685Sdelphij></H3 2131262685Sdelphij><P 2132262685Sdelphij><TT 2133262685SdelphijCLASS="LITERAL" 2134262685Sdelphij>mvaddch()</TT 2135262685Sdelphij> is used to move the cursor to a 2136262685Sdelphijgiven point, and then print. Thus, the calls: 2137262685Sdelphij<PRE 2138262685SdelphijCLASS="PROGRAMLISTING" 2139262685Sdelphij> move(row,col); /* moves the cursor to row<SPAN 2140262685SdelphijCLASS="emphasis" 2141262685Sdelphij><I 2142262685SdelphijCLASS="EMPHASIS" 2143262685Sdelphij>th</I 2144262685Sdelphij></SPAN 2145262685Sdelphij> row and col<SPAN 2146262685SdelphijCLASS="emphasis" 2147262685Sdelphij><I 2148262685SdelphijCLASS="EMPHASIS" 2149262685Sdelphij>th</I 2150262685Sdelphij></SPAN 2151262685Sdelphij> column */ 2152262685Sdelphij addch(ch);</PRE 2153262685Sdelphij> 2154166124Srafancan be replaced by 2155262685Sdelphij<PRE 2156262685SdelphijCLASS="PROGRAMLISTING" 2157262685Sdelphij> mvaddch(row,col,ch);</PRE 2158262685Sdelphij></P 2159262685Sdelphij><P 2160262685Sdelphij><TT 2161262685SdelphijCLASS="LITERAL" 2162262685Sdelphij>waddch()</TT 2163262685Sdelphij> is similar to 2164262685Sdelphij<TT 2165262685SdelphijCLASS="LITERAL" 2166262685Sdelphij>addch()</TT 2167262685Sdelphij>, except that it adds a character into 2168262685Sdelphijthe given window. (Note that <TT 2169262685SdelphijCLASS="LITERAL" 2170262685Sdelphij>addch()</TT 2171262685Sdelphij> adds a 2172262685Sdelphijcharacter into the window <TT 2173262685SdelphijCLASS="LITERAL" 2174262685Sdelphij>stdscr</TT 2175262685Sdelphij>.)</P 2176262685Sdelphij><P 2177262685Sdelphij>In a similar fashion <TT 2178262685SdelphijCLASS="LITERAL" 2179262685Sdelphij>mvwaddch()</TT 2180262685Sdelphij> function is 2181262685Sdelphijused to add a character into the given window at the given coordinates.</P 2182262685Sdelphij><P 2183262685Sdelphij>Now, we are familiar with the basic output function 2184262685Sdelphij<TT 2185262685SdelphijCLASS="LITERAL" 2186262685Sdelphij>addch()</TT 2187262685Sdelphij>. But, if we want to print a string, it 2188262685Sdelphijwould be very annoying to print it character by character. Fortunately, 2189262685Sdelphij<TT 2190262685SdelphijCLASS="LITERAL" 2191262685Sdelphij>ncurses</TT 2192262685Sdelphij> provides <TT 2193262685SdelphijCLASS="LITERAL" 2194262685Sdelphij>printf</TT 2195262685Sdelphij><SPAN 2196262685SdelphijCLASS="emphasis" 2197262685Sdelphij><I 2198262685SdelphijCLASS="EMPHASIS" 2199262685Sdelphij>-like</I 2200262685Sdelphij></SPAN 2201262685Sdelphij> or 2202262685Sdelphij<TT 2203262685SdelphijCLASS="LITERAL" 2204262685Sdelphij>puts</TT 2205262685Sdelphij><SPAN 2206262685SdelphijCLASS="emphasis" 2207262685Sdelphij><I 2208262685SdelphijCLASS="EMPHASIS" 2209262685Sdelphij>-like</I 2210262685Sdelphij></SPAN 2211262685Sdelphij> functions.</P 2212262685Sdelphij></DIV 2213262685Sdelphij><DIV 2214262685SdelphijCLASS="SECT2" 2215262685Sdelphij><HR><H3 2216262685SdelphijCLASS="SECT2" 2217262685Sdelphij><A 2218262685SdelphijNAME="PRINTWCLASS" 2219262685Sdelphij>6.3. printw() class of functions</A 2220262685Sdelphij></H3 2221262685Sdelphij><P 2222262685Sdelphij>These functions are similar to <TT 2223262685SdelphijCLASS="LITERAL" 2224262685Sdelphij>printf()</TT 2225262685Sdelphij> with 2226262685Sdelphijthe added capability of printing at any position on the screen. </P 2227262685Sdelphij><DIV 2228262685SdelphijCLASS="SECT3" 2229262685Sdelphij><HR><H4 2230262685SdelphijCLASS="SECT3" 2231262685Sdelphij><A 2232262685SdelphijNAME="PRINTWMVPRINTW" 2233262685Sdelphij>6.3.1. printw() and mvprintw</A 2234262685Sdelphij></H4 2235262685Sdelphij><P 2236262685Sdelphij>These two functions work much like <TT 2237262685SdelphijCLASS="LITERAL" 2238262685Sdelphij>printf()</TT 2239262685Sdelphij>. 2240262685Sdelphij<TT 2241262685SdelphijCLASS="LITERAL" 2242262685Sdelphij>mvprintw()</TT 2243262685Sdelphij> can be used to move the cursor to a 2244262685Sdelphijposition and then print. If you want to move the cursor first and then print 2245262685Sdelphijusing <TT 2246262685SdelphijCLASS="LITERAL" 2247262685Sdelphij>printw()</TT 2248262685Sdelphij> function, use 2249262685Sdelphij<TT 2250262685SdelphijCLASS="LITERAL" 2251262685Sdelphij>move() </TT 2252262685Sdelphij> first and then use 2253262685Sdelphij<TT 2254262685SdelphijCLASS="LITERAL" 2255262685Sdelphij>printw()</TT 2256262685Sdelphij> though I see no point why one should 2257262685Sdelphijavoid using <TT 2258262685SdelphijCLASS="LITERAL" 2259262685Sdelphij>mvprintw()</TT 2260262685Sdelphij>, you have the 2261262685Sdelphijflexibility to manipulate. </P 2262262685Sdelphij></DIV 2263262685Sdelphij><DIV 2264262685SdelphijCLASS="SECT3" 2265262685Sdelphij><HR><H4 2266262685SdelphijCLASS="SECT3" 2267262685Sdelphij><A 2268262685SdelphijNAME="WPRINTWMVWPRINTW" 2269262685Sdelphij>6.3.2. wprintw() and mvwprintw</A 2270262685Sdelphij></H4 2271262685Sdelphij><P 2272262685Sdelphij>These two functions are similar to above two except that they print in the 2273262685Sdelphijcorresponding window given as argument. </P 2274262685Sdelphij></DIV 2275262685Sdelphij><DIV 2276262685SdelphijCLASS="SECT3" 2277262685Sdelphij><HR><H4 2278262685SdelphijCLASS="SECT3" 2279262685Sdelphij><A 2280262685SdelphijNAME="VWPRINTW" 2281262685Sdelphij>6.3.3. vwprintw()</A 2282262685Sdelphij></H4 2283262685Sdelphij><P 2284262685Sdelphij>This function is similar to <TT 2285262685SdelphijCLASS="LITERAL" 2286262685Sdelphij>vprintf()</TT 2287262685Sdelphij>. This can 2288262685Sdelphijbe used when variable number of arguments are to be printed.</P 2289262685Sdelphij></DIV 2290262685Sdelphij><DIV 2291262685SdelphijCLASS="SECT3" 2292262685Sdelphij><HR><H4 2293262685SdelphijCLASS="SECT3" 2294262685Sdelphij><A 2295262685SdelphijNAME="SIMPLEPRINTWEX" 2296262685Sdelphij>6.3.4. A Simple printw example</A 2297262685Sdelphij></H4 2298262685Sdelphij><DIV 2299262685SdelphijCLASS="EXAMPLE" 2300262685Sdelphij><A 2301262685SdelphijNAME="BPREX" 2302262685Sdelphij></A 2303262685Sdelphij><P 2304262685Sdelphij><B 2305262685Sdelphij>Example 3. A Simple printw example </B 2306262685Sdelphij></P 2307262685Sdelphij><PRE 2308262685SdelphijCLASS="PROGRAMLISTING" 2309262685Sdelphij><SPAN 2310262685SdelphijCLASS="INLINEMEDIAOBJECT" 2311262685Sdelphij>#include <ncurses.h> /* ncurses.h includes stdio.h */ 2312262685Sdelphij#include <string.h> 2313166124Srafan 2314166124Srafanint main() 2315166124Srafan{ 2316262685Sdelphij char mesg[]="Just a string"; /* message to be appeared on the screen */ 2317262685Sdelphij int row,col; /* to store the number of rows and * 2318262685Sdelphij * the number of colums of the screen */ 2319262685Sdelphij initscr(); /* start the curses mode */ 2320262685Sdelphij getmaxyx(stdscr,row,col); /* get the number of rows and columns */ 2321166124Srafan mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg); 2322262685Sdelphij /* print the message at the center of the screen */ 2323166124Srafan mvprintw(row-2,0,"This screen has %d rows and %d columns\n",row,col); 2324166124Srafan printw("Try resizing your window(if possible) and then run this program again"); 2325166124Srafan refresh(); 2326166124Srafan getch(); 2327166124Srafan endwin(); 2328166124Srafan 2329166124Srafan return 0; 2330262685Sdelphij}</SPAN 2331262685Sdelphij></PRE 2332262685Sdelphij></DIV 2333262685Sdelphij><P 2334262685Sdelphij>Above program demonstrates how easy it is to use <TT 2335262685SdelphijCLASS="LITERAL" 2336262685Sdelphij>printw</TT 2337262685Sdelphij>. You just feed the coordinates and the message to be appeared 2338262685Sdelphijon the screen, then it does what you want.</P 2339262685Sdelphij><P 2340262685Sdelphij>The above program introduces us to a new function 2341262685Sdelphij<TT 2342262685SdelphijCLASS="LITERAL" 2343262685Sdelphij>getmaxyx()</TT 2344262685Sdelphij>, a macro defined in 2345262685Sdelphij<TT 2346262685SdelphijCLASS="LITERAL" 2347262685Sdelphij>ncurses.h</TT 2348262685Sdelphij>. It gives the number of columns and 2349262685Sdelphijthe number of rows in a given window. 2350262685Sdelphij<TT 2351262685SdelphijCLASS="LITERAL" 2352262685Sdelphij>getmaxyx()</TT 2353262685Sdelphij> does this by updating the variables 2354262685Sdelphijgiven to it. Since <TT 2355262685SdelphijCLASS="LITERAL" 2356262685Sdelphij>getmaxyx()</TT 2357262685Sdelphij> is not a function 2358262685Sdelphijwe don't pass pointers to it, we just give two integer variables. </P 2359262685Sdelphij></DIV 2360262685Sdelphij></DIV 2361262685Sdelphij><DIV 2362262685SdelphijCLASS="SECT2" 2363262685Sdelphij><HR><H3 2364262685SdelphijCLASS="SECT2" 2365262685Sdelphij><A 2366262685SdelphijNAME="ADDSTRCLASS" 2367262685Sdelphij>6.4. addstr() class of functions</A 2368262685Sdelphij></H3 2369262685Sdelphij><P 2370262685Sdelphij><TT 2371262685SdelphijCLASS="LITERAL" 2372262685Sdelphij>addstr()</TT 2373262685Sdelphij> is used to put a character string into 2374262685Sdelphija given window. This function is similar to calling 2375262685Sdelphij<TT 2376262685SdelphijCLASS="LITERAL" 2377262685Sdelphij>addch()</TT 2378262685Sdelphij> once for each character in a given 2379262685Sdelphijstring. This is true for all output functions. There are other functions from 2380262685Sdelphijthis family such as <TT 2381262685SdelphijCLASS="LITERAL" 2382262685Sdelphij>mvaddstr(),mvwaddstr()</TT 2383262685Sdelphij> and 2384262685Sdelphij<TT 2385262685SdelphijCLASS="LITERAL" 2386262685Sdelphij>waddstr()</TT 2387262685Sdelphij>, which obey the naming convention of 2388262685Sdelphijcurses.(e.g. mvaddstr() is similar to the respective calls move() and then 2389262685Sdelphijaddstr().) Another function of this family is addnstr(), which takes an integer 2390262685Sdelphijparameter(say n) additionally. This function puts at most n characters into the 2391262685Sdelphijscreen. If n is negative, then the entire string will be added. </P 2392262685Sdelphij></DIV 2393262685Sdelphij><DIV 2394262685SdelphijCLASS="SECT2" 2395262685Sdelphij><HR><H3 2396262685SdelphijCLASS="SECT2" 2397262685Sdelphij><A 2398262685SdelphijNAME="ACAUTION" 2399262685Sdelphij>6.5. A word of caution</A 2400262685Sdelphij></H3 2401262685Sdelphij><P 2402262685Sdelphij>All these functions take y co-ordinate first and then x in their arguments. 2403262685SdelphijA common mistake by beginners is to pass x,y in that order. If you are 2404262685Sdelphijdoing too many manipulations of (y,x) co-ordinates, think of dividing the 2405262685Sdelphijscreen into windows and manipulate each one separately. Windows are explained 2406262685Sdelphijin the <A 2407262685SdelphijHREF="#WINDOWS" 2408262685Sdelphij> windows </A 2409262685Sdelphij> section.</P 2410262685Sdelphij></DIV 2411262685Sdelphij></DIV 2412262685Sdelphij><DIV 2413262685SdelphijCLASS="SECT1" 2414262685Sdelphij><HR><H2 2415262685SdelphijCLASS="SECT1" 2416262685Sdelphij><A 2417262685SdelphijNAME="SCANW" 2418262685Sdelphij>7. Input functions</A 2419262685Sdelphij></H2 2420262685Sdelphij><P 2421262685Sdelphij>Well, printing without taking input, is boring. Let's see functions which 2422262685Sdelphijallow us to get input from user. These functions also can be divided into 2423262685Sdelphijthree categories.</P 2424262685Sdelphij><P 2425262685Sdelphij></P 2426262685Sdelphij><OL 2427262685SdelphijTYPE="1" 2428262685Sdelphij><LI 2429262685Sdelphij><P 2430262685Sdelphij>getch() class: Get a character</P 2431262685Sdelphij></LI 2432262685Sdelphij><LI 2433262685Sdelphij><P 2434262685Sdelphij>scanw() class: Get formatted input</P 2435262685Sdelphij></LI 2436262685Sdelphij><LI 2437262685Sdelphij><P 2438262685Sdelphij>getstr() class: Get strings</P 2439262685Sdelphij></LI 2440262685Sdelphij></OL 2441262685Sdelphij><DIV 2442262685SdelphijCLASS="SECT2" 2443262685Sdelphij><HR><H3 2444262685SdelphijCLASS="SECT2" 2445262685Sdelphij><A 2446262685SdelphijNAME="GETCHCLASS" 2447262685Sdelphij>7.1. getch() class of functions</A 2448262685Sdelphij></H3 2449262685Sdelphij><P 2450262685Sdelphij>These functions read a single character from the terminal. But there are several 2451262685Sdelphijsubtle facts to consider. For example if you don't use the function cbreak(), 2452262685Sdelphijcurses will not read your input characters contiguously but will begin read them 2453262685Sdelphijonly after a new line or an EOF is encountered. In order to avoid this, the 2454262685Sdelphijcbreak() function must used so that characters are immediately available to your 2455262685Sdelphijprogram. Another widely used function is noecho(). As the name suggests, when 2456262685Sdelphijthis function is set (used), the characters that are keyed in by the user will 2457262685Sdelphijnot show up on the screen. The two functions cbreak() and noecho() are typical 2458262685Sdelphijexamples of key management. Functions of this genre are explained in the 2459262685Sdelphij<A 2460262685SdelphijHREF="#KEYS" 2461262685Sdelphij>key management section </A 2462262685Sdelphij>.</P 2463262685Sdelphij></DIV 2464262685Sdelphij><DIV 2465262685SdelphijCLASS="SECT2" 2466262685Sdelphij><HR><H3 2467262685SdelphijCLASS="SECT2" 2468262685Sdelphij><A 2469262685SdelphijNAME="SCANWCLASS" 2470262685Sdelphij>7.2. scanw() class of functions</A 2471262685Sdelphij></H3 2472262685Sdelphij><P 2473262685Sdelphij>These functions are similar to <TT 2474262685SdelphijCLASS="LITERAL" 2475262685Sdelphij>scanf()</TT 2476262685Sdelphij> with the 2477262685Sdelphijadded capability of getting the input from any location on the screen.</P 2478262685Sdelphij><DIV 2479262685SdelphijCLASS="SECT3" 2480262685Sdelphij><HR><H4 2481262685SdelphijCLASS="SECT3" 2482262685Sdelphij><A 2483262685SdelphijNAME="SCANWMVSCANW" 2484262685Sdelphij>7.2.1. scanw() and mvscanw</A 2485262685Sdelphij></H4 2486262685Sdelphij><P 2487262685Sdelphij>The usage of these functions is similar to that of 2488262685Sdelphij<TT 2489262685SdelphijCLASS="LITERAL" 2490262685Sdelphij>sscanf()</TT 2491262685Sdelphij>, where the line to be scanned is 2492262685Sdelphijprovided by <TT 2493262685SdelphijCLASS="LITERAL" 2494262685Sdelphij>wgetstr()</TT 2495262685Sdelphij> function. That is, these 2496262685Sdelphijfunctions call to <TT 2497262685SdelphijCLASS="LITERAL" 2498262685Sdelphij>wgetstr()</TT 2499262685Sdelphij> function(explained 2500262685Sdelphijbelow) and uses the resulting line for a scan. </P 2501262685Sdelphij></DIV 2502262685Sdelphij><DIV 2503262685SdelphijCLASS="SECT3" 2504262685Sdelphij><HR><H4 2505262685SdelphijCLASS="SECT3" 2506262685Sdelphij><A 2507262685SdelphijNAME="WSCANWMVWSCANW" 2508262685Sdelphij>7.2.2. wscanw() and mvwscanw()</A 2509262685Sdelphij></H4 2510262685Sdelphij><P 2511262685Sdelphij>These are similar to above two functions except that they read from a window, 2512262685Sdelphijwhich is supplied as one of the arguments to these functions. </P 2513262685Sdelphij></DIV 2514262685Sdelphij><DIV 2515262685SdelphijCLASS="SECT3" 2516262685Sdelphij><HR><H4 2517262685SdelphijCLASS="SECT3" 2518262685Sdelphij><A 2519262685SdelphijNAME="VWSCANW" 2520262685Sdelphij>7.2.3. vwscanw()</A 2521262685Sdelphij></H4 2522262685Sdelphij><P 2523262685Sdelphij>This function is similar to <TT 2524262685SdelphijCLASS="LITERAL" 2525262685Sdelphij>vscanf()</TT 2526262685Sdelphij>. This can 2527262685Sdelphijbe used when a variable number of arguments are to be scanned.</P 2528262685Sdelphij></DIV 2529262685Sdelphij></DIV 2530262685Sdelphij><DIV 2531262685SdelphijCLASS="SECT2" 2532262685Sdelphij><HR><H3 2533262685SdelphijCLASS="SECT2" 2534262685Sdelphij><A 2535262685SdelphijNAME="GETSTRCLASS" 2536262685Sdelphij>7.3. getstr() class of functions</A 2537262685Sdelphij></H3 2538262685Sdelphij><P 2539262685Sdelphij>These functions are used to get strings from the terminal. In essence, this 2540262685Sdelphijfunction performs the same task as would be achieved by a series of calls to 2541262685Sdelphij<TT 2542262685SdelphijCLASS="LITERAL" 2543262685Sdelphij>getch()</TT 2544262685Sdelphij> until a newline, carriage return, or 2545262685Sdelphijend-of-file is received. The resulting string of characters are pointed to by 2546262685Sdelphij<TT 2547262685SdelphijCLASS="LITERAL" 2548262685Sdelphij>str</TT 2549262685Sdelphij>, which is a character pointer provided by 2550262685Sdelphijthe user.</P 2551262685Sdelphij></DIV 2552262685Sdelphij><DIV 2553262685SdelphijCLASS="SECT2" 2554262685Sdelphij><HR><H3 2555262685SdelphijCLASS="SECT2" 2556262685Sdelphij><A 2557262685SdelphijNAME="GETSTREX" 2558262685Sdelphij>7.4. Some examples</A 2559262685Sdelphij></H3 2560262685Sdelphij><DIV 2561262685SdelphijCLASS="EXAMPLE" 2562262685Sdelphij><A 2563262685SdelphijNAME="BSCEX" 2564262685Sdelphij></A 2565262685Sdelphij><P 2566262685Sdelphij><B 2567262685Sdelphij>Example 4. A Simple scanw example </B 2568262685Sdelphij></P 2569262685Sdelphij><PRE 2570262685SdelphijCLASS="PROGRAMLISTING" 2571262685Sdelphij><SPAN 2572262685SdelphijCLASS="INLINEMEDIAOBJECT" 2573262685Sdelphij>#include <ncurses.h> /* ncurses.h includes stdio.h */ 2574262685Sdelphij#include <string.h> 2575166124Srafan 2576166124Srafanint main() 2577166124Srafan{ 2578262685Sdelphij char mesg[]="Enter a string: "; /* message to be appeared on the screen */ 2579166124Srafan char str[80]; 2580262685Sdelphij int row,col; /* to store the number of rows and * 2581262685Sdelphij * the number of colums of the screen */ 2582262685Sdelphij initscr(); /* start the curses mode */ 2583262685Sdelphij getmaxyx(stdscr,row,col); /* get the number of rows and columns */ 2584166124Srafan mvprintw(row/2,(col-strlen(mesg))/2,"%s",mesg); 2585262685Sdelphij /* print the message at the center of the screen */ 2586166124Srafan getstr(str); 2587166124Srafan mvprintw(LINES - 2, 0, "You Entered: %s", str); 2588166124Srafan getch(); 2589166124Srafan endwin(); 2590166124Srafan 2591166124Srafan return 0; 2592262685Sdelphij}</SPAN 2593262685Sdelphij></PRE 2594262685Sdelphij></DIV 2595262685Sdelphij></DIV 2596262685Sdelphij></DIV 2597262685Sdelphij><DIV 2598262685SdelphijCLASS="SECT1" 2599262685Sdelphij><HR><H2 2600262685SdelphijCLASS="SECT1" 2601262685Sdelphij><A 2602262685SdelphijNAME="ATTRIB" 2603262685Sdelphij>8. Attributes</A 2604262685Sdelphij></H2 2605262685Sdelphij><P 2606262685Sdelphij>We have seen an example of how attributes can be used to print characters with 2607262685Sdelphijsome special effects. Attributes, when set prudently, can present information in 2608262685Sdelphijan easy, understandable manner. The following program takes a C file as input 2609262685Sdelphijand prints the file with comments in bold. Scan through the code. </P 2610262685Sdelphij><DIV 2611262685SdelphijCLASS="EXAMPLE" 2612262685Sdelphij><A 2613262685SdelphijNAME="BSIAT" 2614262685Sdelphij></A 2615262685Sdelphij><P 2616262685Sdelphij><B 2617262685Sdelphij>Example 5. A Simple Attributes example </B 2618262685Sdelphij></P 2619262685Sdelphij><PRE 2620262685SdelphijCLASS="PROGRAMLISTING" 2621262685Sdelphij><SPAN 2622262685SdelphijCLASS="INLINEMEDIAOBJECT" 2623262685Sdelphij>/* pager functionality by Joseph Spainhour" <spainhou@bellsouth.net> */ 2624262685Sdelphij#include <ncurses.h> 2625262685Sdelphij#include <stdlib.h> 2626166124Srafan 2627166124Srafanint main(int argc, char *argv[]) 2628166124Srafan{ 2629166124Srafan int ch, prev, row, col; 2630166124Srafan prev = EOF; 2631166124Srafan FILE *fp; 2632166124Srafan int y, x; 2633166124Srafan 2634166124Srafan if(argc != 2) 2635166124Srafan { 2636262685Sdelphij printf("Usage: %s <a c file name>\n", argv[0]); 2637166124Srafan exit(1); 2638166124Srafan } 2639166124Srafan fp = fopen(argv[1], "r"); 2640166124Srafan if(fp == NULL) 2641166124Srafan { 2642166124Srafan perror("Cannot open input file"); 2643166124Srafan exit(1); 2644166124Srafan } 2645262685Sdelphij initscr(); /* Start curses mode */ 2646262685Sdelphij getmaxyx(stdscr, row, col); /* find the boundaries of the screeen */ 2647262685Sdelphij while((ch = fgetc(fp)) != EOF) /* read the file till we reach the end */ 2648166124Srafan { 2649262685Sdelphij getyx(stdscr, y, x); /* get the current curser position */ 2650262685Sdelphij if(y == (row - 1)) /* are we are at the end of the screen */ 2651166124Srafan { 2652262685Sdelphij printw("<-Press Any Key->"); /* tell the user to press a key */ 2653166124Srafan getch(); 2654262685Sdelphij clear(); /* clear the screen */ 2655262685Sdelphij move(0, 0); /* start at the beginning of the screen */ 2656166124Srafan } 2657262685Sdelphij if(prev == '/' && ch == '*') /* If it is / and * then only 2658262685Sdelphij * switch bold on */ 2659166124Srafan { 2660262685Sdelphij attron(A_BOLD); /* cut bold on */ 2661262685Sdelphij getyx(stdscr, y, x); /* get the current curser position */ 2662262685Sdelphij move(y, x - 1); /* back up one space */ 2663262685Sdelphij printw("%c%c", '/', ch); /* The actual printing is done here */ 2664166124Srafan } 2665166124Srafan else 2666166124Srafan printw("%c", ch); 2667166124Srafan refresh(); 2668262685Sdelphij if(prev == '*' && ch == '/') 2669262685Sdelphij attroff(A_BOLD); /* Switch it off once we got * 2670262685Sdelphij * and then / */ 2671166124Srafan prev = ch; 2672166124Srafan } 2673262685Sdelphij endwin(); /* End curses mode */ 2674166124Srafan fclose(fp); 2675166124Srafan return 0; 2676262685Sdelphij}</SPAN 2677262685Sdelphij></PRE 2678262685Sdelphij></DIV 2679262685Sdelphij><P 2680262685Sdelphij> 2681262685SdelphijDon't worry about all those initialization and other crap. Concentrate on 2682262685Sdelphijthe while loop. It reads each character in the file and searches for the 2683262685Sdelphijpattern /*. Once it spots the pattern, it switches the BOLD attribute on with 2684262685Sdelphij<TT 2685262685SdelphijCLASS="LITERAL" 2686262685Sdelphij> attron()</TT 2687262685Sdelphij> . When we get the pattern */ it is 2688262685Sdelphijswitched off by <TT 2689262685SdelphijCLASS="LITERAL" 2690262685Sdelphij> attroff()</TT 2691262685Sdelphij> .</P 2692262685Sdelphij><P 2693262685Sdelphij> 2694262685SdelphijThe above program also introduces us to two useful functions 2695262685Sdelphij<TT 2696262685SdelphijCLASS="LITERAL" 2697262685Sdelphij>getyx() </TT 2698262685Sdelphij> and 2699262685Sdelphij<TT 2700262685SdelphijCLASS="LITERAL" 2701262685Sdelphij>move()</TT 2702262685Sdelphij>. The first function gets the 2703262685Sdelphijco-ordinates of the present cursor into the variables y, x. Since getyx() is a 2704166124Srafanmacro we don't have to pass pointers to variables. The function 2705262685Sdelphij<TT 2706262685SdelphijCLASS="LITERAL" 2707262685Sdelphij>move()</TT 2708262685Sdelphij> moves the cursor to the co-ordinates 2709262685Sdelphijgiven to it. </P 2710262685Sdelphij><P 2711262685Sdelphij> 2712262685SdelphijThe above program is really a simple one which doesn't do much. On these lines 2713262685Sdelphijone could write a more useful program which reads a C file, parses it and prints 2714262685Sdelphijit in different colors. One could even extend it to other languages as well.</P 2715262685Sdelphij><DIV 2716262685SdelphijCLASS="SECT2" 2717262685Sdelphij><HR><H3 2718262685SdelphijCLASS="SECT2" 2719262685Sdelphij><A 2720262685SdelphijNAME="ATTRIBDETAILS" 2721262685Sdelphij>8.1. The details</A 2722262685Sdelphij></H3 2723262685Sdelphij><P 2724262685Sdelphij>Let's get into more details of attributes. The functions <TT 2725262685SdelphijCLASS="LITERAL" 2726262685Sdelphij>attron(), attroff(), attrset() </TT 2727262685Sdelphij>, and their sister functions 2728262685Sdelphij<TT 2729262685SdelphijCLASS="LITERAL" 2730262685Sdelphij> attr_get()</TT 2731262685Sdelphij> etc.. can be used to switch 2732262685Sdelphijattributes on/off , get attributes and produce a colorful display.</P 2733262685Sdelphij><P 2734262685Sdelphij>The functions attron and attroff take a bit-mask of attributes and switch them 2735262685Sdelphijon or off, respectively. The following video attributes, which are defined in 2736262685Sdelphij<curses.h> can be passed to these functions. </P 2737262685Sdelphij><PRE 2738262685SdelphijCLASS="PROGRAMLISTING" 2739262685Sdelphij> 2740166124Srafan A_NORMAL Normal display (no highlight) 2741166124Srafan A_STANDOUT Best highlighting mode of the terminal. 2742166124Srafan A_UNDERLINE Underlining 2743166124Srafan A_REVERSE Reverse video 2744166124Srafan A_BLINK Blinking 2745166124Srafan A_DIM Half bright 2746166124Srafan A_BOLD Extra bright or bold 2747166124Srafan A_PROTECT Protected mode 2748166124Srafan A_INVIS Invisible or blank mode 2749166124Srafan A_ALTCHARSET Alternate character set 2750166124Srafan A_CHARTEXT Bit-mask to extract a character 2751166124Srafan COLOR_PAIR(n) Color-pair number n 2752262685Sdelphij </PRE 2753262685Sdelphij><P 2754262685Sdelphij> 2755262685SdelphijThe last one is the most colorful one :-) Colors are explained in the 2756262685Sdelphij<A 2757262685SdelphijHREF="#color" 2758262685SdelphijTARGET="_top" 2759262685Sdelphij>next sections</A 2760262685Sdelphij>.</P 2761262685Sdelphij><P 2762262685Sdelphij>We can OR(|) any number of above attributes to get a combined effect. If you 2763262685Sdelphijwanted reverse video with blinking characters you can use</P 2764262685Sdelphij><PRE 2765262685SdelphijCLASS="PROGRAMLISTING" 2766262685Sdelphij> attron(A_REVERSE | A_BLINK);</PRE 2767262685Sdelphij></DIV 2768262685Sdelphij><DIV 2769262685SdelphijCLASS="SECT2" 2770262685Sdelphij><HR><H3 2771262685SdelphijCLASS="SECT2" 2772262685Sdelphij><A 2773262685SdelphijNAME="ATTRONVSATTRSET" 2774262685Sdelphij>8.2. attron() vs attrset()</A 2775262685Sdelphij></H3 2776262685Sdelphij><P 2777262685Sdelphij>Then what is the difference between attron() and attrset()? attrset sets the 2778262685Sdelphijattributes of window whereas attron just switches on the attribute given to it. 2779262685SdelphijSo attrset() fully overrides whatever attributes the window previously had and 2780262685Sdelphijsets it to the new attribute(s). Similarly attroff() just switches off the 2781262685Sdelphijattribute(s) given to it as an argument. This gives us the flexibility of 2782262685Sdelphijmanaging attributes easily.But if you use them carelessly you may loose track of 2783262685Sdelphijwhat attributes the window has and garble the display. This is especially true 2784262685Sdelphijwhile managing menus with colors and highlighting. So decide on a consistent 2785262685Sdelphijpolicy and stick to it. You can always use <TT 2786262685SdelphijCLASS="LITERAL" 2787262685Sdelphij> standend()</TT 2788262685Sdelphij> which is equivalent to <TT 2789262685SdelphijCLASS="LITERAL" 2790262685Sdelphij> attrset(A_NORMAL)</TT 2791262685Sdelphij> which turns off all attributes and brings you to normal mode.</P 2792262685Sdelphij></DIV 2793262685Sdelphij><DIV 2794262685SdelphijCLASS="SECT2" 2795262685Sdelphij><HR><H3 2796262685SdelphijCLASS="SECT2" 2797262685Sdelphij><A 2798262685SdelphijNAME="ATTR_GET" 2799262685Sdelphij>8.3. attr_get()</A 2800262685Sdelphij></H3 2801262685Sdelphij><P 2802262685Sdelphij> The function attr_get() gets the current attributes and color pair of the 2803262685Sdelphijwindow. Though we might not use this as often as the above functions, this is 2804262685Sdelphijuseful in scanning areas of screen. Say we wanted to do some complex update on 2805262685Sdelphijscreen and we are not sure what attribute each character is associated with. 2806262685SdelphijThen this function can be used with either attrset or attron to produce the 2807262685Sdelphijdesired effect. </P 2808262685Sdelphij></DIV 2809262685Sdelphij><DIV 2810262685SdelphijCLASS="SECT2" 2811262685Sdelphij><HR><H3 2812262685SdelphijCLASS="SECT2" 2813262685Sdelphij><A 2814262685SdelphijNAME="ATTR_FUNCS" 2815262685Sdelphij>8.4. attr_ functions</A 2816262685Sdelphij></H3 2817262685Sdelphij><P 2818262685Sdelphij>There are series of functions like attr_set(), attr_on etc.. These are similar 2819262685Sdelphijto above functions except that they take parameters of type 2820262685Sdelphij<TT 2821262685SdelphijCLASS="LITERAL" 2822262685Sdelphij>attr_t</TT 2823262685Sdelphij>.</P 2824262685Sdelphij></DIV 2825262685Sdelphij><DIV 2826262685SdelphijCLASS="SECT2" 2827262685Sdelphij><HR><H3 2828262685SdelphijCLASS="SECT2" 2829262685Sdelphij><A 2830262685SdelphijNAME="WATTRFUNCS" 2831262685Sdelphij>8.5. wattr functions</A 2832262685Sdelphij></H3 2833262685Sdelphij><P 2834262685Sdelphij>For each of the above functions we have a corresponding function with 'w' which 2835262685Sdelphijoperates on a particular window. The above functions operate on stdscr. </P 2836262685Sdelphij></DIV 2837262685Sdelphij><DIV 2838262685SdelphijCLASS="SECT2" 2839262685Sdelphij><HR><H3 2840262685SdelphijCLASS="SECT2" 2841262685Sdelphij><A 2842262685SdelphijNAME="CHGAT" 2843262685Sdelphij>8.6. chgat() functions</A 2844262685Sdelphij></H3 2845262685Sdelphij><P 2846262685Sdelphij>The function chgat() is listed in the end of the man page curs_attr. It actually 2847262685Sdelphijis a useful one. This function can be used to set attributes for a group of 2848262685Sdelphijcharacters without moving. I mean it !!! without moving the cursor :-) It 2849262685Sdelphijchanges the attributes of a given number of characters starting at the current 2850262685Sdelphijcursor location.</P 2851262685Sdelphij><P 2852262685Sdelphij>We can give -1 as the character count to update till end of line. If you want to 2853262685Sdelphijchange attributes of characters from current position to end of line, just use 2854262685Sdelphijthis.</P 2855262685Sdelphij><PRE 2856262685SdelphijCLASS="PROGRAMLISTING" 2857262685Sdelphij> chgat(-1, A_REVERSE, 0, NULL);</PRE 2858262685Sdelphij><P 2859262685Sdelphij> 2860262685SdelphijThis function is useful when changing attributes for characters that are 2861262685Sdelphijalready on the screen. Move to the character from which you want to change and 2862262685Sdelphijchange the attribute. </P 2863262685Sdelphij><P 2864262685Sdelphij>Other functions wchgat(), mvchgat(), wchgat() behave similarly except that the w 2865262685Sdelphijfunctions operate on the particular window. The mv functions first move the 2866262685Sdelphijcursor then perform the work given to them. Actually chgat is a macro which is 2867262685Sdelphijreplaced by a wchgat() with stdscr as the window. Most of the "w-less" functions 2868262685Sdelphijare macros.</P 2869262685Sdelphij><DIV 2870262685SdelphijCLASS="EXAMPLE" 2871262685Sdelphij><A 2872262685SdelphijNAME="BWICH" 2873262685Sdelphij></A 2874262685Sdelphij><P 2875262685Sdelphij><B 2876262685Sdelphij>Example 6. Chgat() Usage example </B 2877262685Sdelphij></P 2878262685Sdelphij><PRE 2879262685SdelphijCLASS="PROGRAMLISTING" 2880262685Sdelphij><SPAN 2881262685SdelphijCLASS="INLINEMEDIAOBJECT" 2882262685Sdelphij>#include <ncurses.h> 2883166124Srafan 2884166124Srafanint main(int argc, char *argv[]) 2885262685Sdelphij{ initscr(); /* Start curses mode */ 2886262685Sdelphij start_color(); /* Start color functionality */ 2887262685Sdelphij 2888262685Sdelphij init_pair(1, COLOR_CYAN, COLOR_BLACK); 2889262685Sdelphij printw("A Big string which i didn't care to type fully "); 2890262685Sdelphij mvchgat(0, 0, -1, A_BLINK, 1, NULL); 2891262685Sdelphij /* 2892262685Sdelphij * First two parameters specify the position at which to start 2893262685Sdelphij * Third parameter number of characters to update. -1 means till 2894262685Sdelphij * end of line 2895262685Sdelphij * Forth parameter is the normal attribute you wanted to give 2896262685Sdelphij * to the charcter 2897262685Sdelphij * Fifth is the color index. It is the index given during init_pair() 2898262685Sdelphij * use 0 if you didn't want color 2899262685Sdelphij * Sixth one is always NULL 2900262685Sdelphij */ 2901262685Sdelphij refresh(); 2902262685Sdelphij getch(); 2903262685Sdelphij endwin(); /* End curses mode */ 2904262685Sdelphij return 0; 2905262685Sdelphij}</SPAN 2906262685Sdelphij></PRE 2907262685Sdelphij></DIV 2908262685Sdelphij><P 2909262685Sdelphij>This example also introduces us to the color world of curses. Colors will be 2910262685Sdelphijexplained in detail later. Use 0 for no color.</P 2911262685Sdelphij></DIV 2912262685Sdelphij></DIV 2913262685Sdelphij><DIV 2914262685SdelphijCLASS="SECT1" 2915262685Sdelphij><HR><H2 2916262685SdelphijCLASS="SECT1" 2917262685Sdelphij><A 2918262685SdelphijNAME="WINDOWS" 2919262685Sdelphij>9. Windows</A 2920262685Sdelphij></H2 2921262685Sdelphij><P 2922262685Sdelphij>Windows form the most important concept in curses. You have seen the standard 2923262685Sdelphijwindow stdscr above where all the functions implicitly operated on this window. 2924262685SdelphijNow to make design even a simplest GUI, you need to resort to windows. The main 2925262685Sdelphijreason you may want to use windows is to manipulate parts of the screen 2926262685Sdelphijseparately, for better efficiency, by updating only the windows that need to be 2927262685Sdelphijchanged and for a better design. I would say the last reason is the most 2928262685Sdelphijimportant in going for windows. You should always strive for a better and 2929262685Sdelphijeasy-to-manage design in your programs. If you are writing big, complex GUIs 2930262685Sdelphijthis is of pivotal importance before you start doing anything.</P 2931262685Sdelphij><DIV 2932262685SdelphijCLASS="SECT2" 2933262685Sdelphij><HR><H3 2934262685SdelphijCLASS="SECT2" 2935262685Sdelphij><A 2936262685SdelphijNAME="WINDOWBASICS" 2937262685Sdelphij>9.1. The basics</A 2938262685Sdelphij></H3 2939262685Sdelphij><P 2940262685Sdelphij>A Window can be created by calling the function 2941262685Sdelphij<TT 2942262685SdelphijCLASS="LITERAL" 2943262685Sdelphij>newwin()</TT 2944262685Sdelphij>. It doesn't create any thing on the 2945262685Sdelphijscreen actually. It allocates memory for a structure to manipulate the window 2946262685Sdelphijand updates the structure with data regarding the window like it's size, beginy, 2947262685Sdelphijbeginx etc.. Hence in curses, a window is just an abstraction of an imaginary 2948262685Sdelphijwindow, which can be manipulated independent of other parts of screen. The 2949262685Sdelphijfunction newwin() returns a pointer to structure WINDOW, which can be passed to 2950262685Sdelphijwindow related functions like wprintw() etc.. Finally the window can be 2951262685Sdelphijdestroyed with delwin(). It will deallocate the memory associated with the 2952262685Sdelphijwindow structure.</P 2953262685Sdelphij></DIV 2954262685Sdelphij><DIV 2955262685SdelphijCLASS="SECT2" 2956262685Sdelphij><HR><H3 2957262685SdelphijCLASS="SECT2" 2958262685Sdelphij><A 2959262685SdelphijNAME="LETBEWINDOW" 2960262685Sdelphij>9.2. Let there be a Window !!!</A 2961262685Sdelphij></H3 2962262685Sdelphij><P 2963262685Sdelphij>What fun is it, if a window is created and we can't see it. So the fun part 2964262685Sdelphijbegins by displaying the window. The function 2965262685Sdelphij<TT 2966262685SdelphijCLASS="LITERAL" 2967262685Sdelphij>box()</TT 2968262685Sdelphij> can be used to draw a border around the 2969262685Sdelphijwindow. Let's explore these functions in more detail in this example.</P 2970262685Sdelphij><DIV 2971262685SdelphijCLASS="EXAMPLE" 2972262685Sdelphij><A 2973262685SdelphijNAME="BWIBO" 2974262685Sdelphij></A 2975262685Sdelphij><P 2976262685Sdelphij><B 2977262685Sdelphij>Example 7. Window Border example </B 2978262685Sdelphij></P 2979262685Sdelphij><PRE 2980262685SdelphijCLASS="PROGRAMLISTING" 2981262685Sdelphij><SPAN 2982262685SdelphijCLASS="INLINEMEDIAOBJECT" 2983262685Sdelphij>#include <ncurses.h> 2984166124Srafan 2985166124Srafan 2986166124SrafanWINDOW *create_newwin(int height, int width, int starty, int startx); 2987166124Srafanvoid destroy_win(WINDOW *local_win); 2988166124Srafan 2989166124Srafanint main(int argc, char *argv[]) 2990262685Sdelphij{ WINDOW *my_win; 2991262685Sdelphij int startx, starty, width, height; 2992262685Sdelphij int ch; 2993166124Srafan 2994262685Sdelphij initscr(); /* Start curses mode */ 2995262685Sdelphij cbreak(); /* Line buffering disabled, Pass on 2996262685Sdelphij * everty thing to me */ 2997262685Sdelphij keypad(stdscr, TRUE); /* I need that nifty F1 */ 2998166124Srafan 2999262685Sdelphij height = 3; 3000262685Sdelphij width = 10; 3001262685Sdelphij starty = (LINES - height) / 2; /* Calculating for a center placement */ 3002262685Sdelphij startx = (COLS - width) / 2; /* of the window */ 3003262685Sdelphij printw("Press F1 to exit"); 3004262685Sdelphij refresh(); 3005262685Sdelphij my_win = create_newwin(height, width, starty, startx); 3006166124Srafan 3007262685Sdelphij while((ch = getch()) != KEY_F(1)) 3008262685Sdelphij { switch(ch) 3009262685Sdelphij { case KEY_LEFT: 3010262685Sdelphij destroy_win(my_win); 3011262685Sdelphij my_win = create_newwin(height, width, starty,--startx); 3012262685Sdelphij break; 3013262685Sdelphij case KEY_RIGHT: 3014262685Sdelphij destroy_win(my_win); 3015262685Sdelphij my_win = create_newwin(height, width, starty,++startx); 3016262685Sdelphij break; 3017262685Sdelphij case KEY_UP: 3018262685Sdelphij destroy_win(my_win); 3019262685Sdelphij my_win = create_newwin(height, width, --starty,startx); 3020262685Sdelphij break; 3021262685Sdelphij case KEY_DOWN: 3022262685Sdelphij destroy_win(my_win); 3023262685Sdelphij my_win = create_newwin(height, width, ++starty,startx); 3024262685Sdelphij break; 3025262685Sdelphij } 3026262685Sdelphij } 3027262685Sdelphij 3028262685Sdelphij endwin(); /* End curses mode */ 3029262685Sdelphij return 0; 3030166124Srafan} 3031166124Srafan 3032166124SrafanWINDOW *create_newwin(int height, int width, int starty, int startx) 3033262685Sdelphij{ WINDOW *local_win; 3034166124Srafan 3035262685Sdelphij local_win = newwin(height, width, starty, startx); 3036262685Sdelphij box(local_win, 0 , 0); /* 0, 0 gives default characters 3037262685Sdelphij * for the vertical and horizontal 3038262685Sdelphij * lines */ 3039262685Sdelphij wrefresh(local_win); /* Show that box */ 3040166124Srafan 3041262685Sdelphij return local_win; 3042166124Srafan} 3043166124Srafan 3044166124Srafanvoid destroy_win(WINDOW *local_win) 3045262685Sdelphij{ 3046262685Sdelphij /* box(local_win, ' ', ' '); : This won't produce the desired 3047262685Sdelphij * result of erasing the window. It will leave it's four corners 3048262685Sdelphij * and so an ugly remnant of window. 3049262685Sdelphij */ 3050262685Sdelphij wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' '); 3051262685Sdelphij /* The parameters taken are 3052262685Sdelphij * 1. win: the window on which to operate 3053262685Sdelphij * 2. ls: character to be used for the left side of the window 3054262685Sdelphij * 3. rs: character to be used for the right side of the window 3055262685Sdelphij * 4. ts: character to be used for the top side of the window 3056262685Sdelphij * 5. bs: character to be used for the bottom side of the window 3057262685Sdelphij * 6. tl: character to be used for the top left corner of the window 3058262685Sdelphij * 7. tr: character to be used for the top right corner of the window 3059262685Sdelphij * 8. bl: character to be used for the bottom left corner of the window 3060262685Sdelphij * 9. br: character to be used for the bottom right corner of the window 3061262685Sdelphij */ 3062262685Sdelphij wrefresh(local_win); 3063262685Sdelphij delwin(local_win); 3064262685Sdelphij}</SPAN 3065262685Sdelphij></PRE 3066262685Sdelphij></DIV 3067262685Sdelphij></DIV 3068262685Sdelphij><DIV 3069262685SdelphijCLASS="SECT2" 3070262685Sdelphij><HR><H3 3071262685SdelphijCLASS="SECT2" 3072262685Sdelphij><A 3073262685SdelphijNAME="BORDEREXEXPL" 3074262685Sdelphij>9.3. Explanation</A 3075262685Sdelphij></H3 3076262685Sdelphij><P 3077262685Sdelphij>Don't scream. I know it's a big example. But I have to explain some important 3078262685Sdelphijthings here :-). This program creates a rectangular window that can be moved 3079262685Sdelphijwith left, right, up, down arrow keys. It repeatedly creates and destroys 3080262685Sdelphijwindows as user press a key. Don't go beyond the screen limits. Checking for 3081262685Sdelphijthose limits is left as an exercise for the reader. Let's dissect it by line by line.</P 3082262685Sdelphij><P 3083262685Sdelphij>The <TT 3084262685SdelphijCLASS="LITERAL" 3085262685Sdelphij>create_newwin()</TT 3086262685Sdelphij> function creates a window 3087262685Sdelphijwith <TT 3088262685SdelphijCLASS="LITERAL" 3089262685Sdelphij>newwin() </TT 3090262685Sdelphij> and displays a border around it 3091262685Sdelphijwith box. The function <TT 3092262685SdelphijCLASS="LITERAL" 3093262685Sdelphij> destroy_win()</TT 3094262685Sdelphij> first 3095262685Sdelphijerases the window from screen by painting a border with ' ' character and then 3096262685Sdelphijcalling <TT 3097262685SdelphijCLASS="LITERAL" 3098262685Sdelphij>delwin()</TT 3099262685Sdelphij> to deallocate memory related 3100262685Sdelphijto it. Depending on the key the user presses, starty or startx is changed and a 3101262685Sdelphijnew window is created.</P 3102262685Sdelphij><P 3103262685Sdelphij>In the destroy_win, as you can see, I used wborder instead of box. The reason is 3104262685Sdelphijwritten in the comments (You missed it. I know. Read the code :-)). wborder 3105262685Sdelphijdraws a border around the window with the characters given to it as the 4 corner 3106262685Sdelphijpoints and the 4 lines. To put it clearly, if you have called wborder as below: 3107262685Sdelphij<PRE 3108262685SdelphijCLASS="PROGRAMLISTING" 3109262685Sdelphij> wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');</PRE 3110262685Sdelphij></P 3111262685Sdelphij><P 3112262685Sdelphij>it produces some thing like </P 3113262685Sdelphij><PRE 3114262685SdelphijCLASS="PROGRAMLISTING" 3115262685Sdelphij> +------------+ 3116166124Srafan | | 3117166124Srafan | | 3118166124Srafan | | 3119166124Srafan | | 3120166124Srafan | | 3121166124Srafan | | 3122262685Sdelphij +------------+</PRE 3123262685Sdelphij></DIV 3124262685Sdelphij><DIV 3125262685SdelphijCLASS="SECT2" 3126262685Sdelphij><HR><H3 3127262685SdelphijCLASS="SECT2" 3128262685Sdelphij><A 3129262685SdelphijNAME="OTHERSTUFF" 3130262685Sdelphij>9.4. The other stuff in the example</A 3131262685Sdelphij></H3 3132262685Sdelphij><P 3133262685Sdelphij>You can also see in the above examples, that I have used the variables COLS, 3134262685SdelphijLINES which are initialized to the screen sizes after initscr(). They can be 3135262685Sdelphijuseful in finding screen dimensions and finding the center co-ordinate of the 3136262685Sdelphijscreen as above. The function <TT 3137262685SdelphijCLASS="LITERAL" 3138262685Sdelphij>getch()</TT 3139262685Sdelphij> as usual 3140262685Sdelphijgets the key from keyboard and according to the key it does the corresponding 3141262685Sdelphijwork. This type of switch- case is very common in any GUI based programs.</P 3142262685Sdelphij></DIV 3143262685Sdelphij><DIV 3144262685SdelphijCLASS="SECT2" 3145262685Sdelphij><HR><H3 3146262685SdelphijCLASS="SECT2" 3147262685Sdelphij><A 3148262685SdelphijNAME="OTHERBORDERFUNCS" 3149262685Sdelphij>9.5. Other Border functions</A 3150262685Sdelphij></H3 3151262685Sdelphij><P 3152262685Sdelphij>Above program is grossly inefficient in that with each press of a key, a window 3153262685Sdelphijis destroyed and another is created. So let's write a more efficient program 3154262685Sdelphijwhich uses other border related functions.</P 3155262685Sdelphij><P 3156262685Sdelphij>The following program uses <TT 3157262685SdelphijCLASS="LITERAL" 3158262685Sdelphij>mvhline()</TT 3159262685Sdelphij> and 3160262685Sdelphij<TT 3161262685SdelphijCLASS="LITERAL" 3162262685Sdelphij>mvvline()</TT 3163262685Sdelphij> to achieve similar effect. These two 3164262685Sdelphijfunctions are simple. They create a horizontal or vertical line of the specified 3165262685Sdelphijlength at the specified position.</P 3166262685Sdelphij><DIV 3167262685SdelphijCLASS="EXAMPLE" 3168262685Sdelphij><A 3169262685SdelphijNAME="BOTBO" 3170262685Sdelphij></A 3171262685Sdelphij><P 3172262685Sdelphij><B 3173262685Sdelphij>Example 8. More border functions</B 3174262685Sdelphij></P 3175262685Sdelphij><PRE 3176262685SdelphijCLASS="PROGRAMLISTING" 3177262685Sdelphij><SPAN 3178262685SdelphijCLASS="INLINEMEDIAOBJECT" 3179262685Sdelphij>#include <ncurses.h> 3180166124Srafan 3181166124Srafantypedef struct _win_border_struct { 3182262685Sdelphij chtype ls, rs, ts, bs, 3183262685Sdelphij tl, tr, bl, br; 3184166124Srafan}WIN_BORDER; 3185166124Srafan 3186166124Srafantypedef struct _WIN_struct { 3187166124Srafan 3188262685Sdelphij int startx, starty; 3189262685Sdelphij int height, width; 3190262685Sdelphij WIN_BORDER border; 3191166124Srafan}WIN; 3192166124Srafan 3193166124Srafanvoid init_win_params(WIN *p_win); 3194166124Srafanvoid print_win_params(WIN *p_win); 3195166124Srafanvoid create_box(WIN *win, bool flag); 3196166124Srafan 3197166124Srafanint main(int argc, char *argv[]) 3198262685Sdelphij{ WIN win; 3199262685Sdelphij int ch; 3200166124Srafan 3201262685Sdelphij initscr(); /* Start curses mode */ 3202262685Sdelphij start_color(); /* Start the color functionality */ 3203262685Sdelphij cbreak(); /* Line buffering disabled, Pass on 3204262685Sdelphij * everty thing to me */ 3205262685Sdelphij keypad(stdscr, TRUE); /* I need that nifty F1 */ 3206262685Sdelphij noecho(); 3207262685Sdelphij init_pair(1, COLOR_CYAN, COLOR_BLACK); 3208166124Srafan 3209262685Sdelphij /* Initialize the window parameters */ 3210262685Sdelphij init_win_params(&win); 3211262685Sdelphij print_win_params(&win); 3212166124Srafan 3213262685Sdelphij attron(COLOR_PAIR(1)); 3214262685Sdelphij printw("Press F1 to exit"); 3215262685Sdelphij refresh(); 3216262685Sdelphij attroff(COLOR_PAIR(1)); 3217262685Sdelphij 3218262685Sdelphij create_box(&win, TRUE); 3219262685Sdelphij while((ch = getch()) != KEY_F(1)) 3220262685Sdelphij { switch(ch) 3221262685Sdelphij { case KEY_LEFT: 3222262685Sdelphij create_box(&win, FALSE); 3223262685Sdelphij --win.startx; 3224262685Sdelphij create_box(&win, TRUE); 3225262685Sdelphij break; 3226262685Sdelphij case KEY_RIGHT: 3227262685Sdelphij create_box(&win, FALSE); 3228262685Sdelphij ++win.startx; 3229262685Sdelphij create_box(&win, TRUE); 3230262685Sdelphij break; 3231262685Sdelphij case KEY_UP: 3232262685Sdelphij create_box(&win, FALSE); 3233262685Sdelphij --win.starty; 3234262685Sdelphij create_box(&win, TRUE); 3235262685Sdelphij break; 3236262685Sdelphij case KEY_DOWN: 3237262685Sdelphij create_box(&win, FALSE); 3238262685Sdelphij ++win.starty; 3239262685Sdelphij create_box(&win, TRUE); 3240262685Sdelphij break; 3241262685Sdelphij } 3242262685Sdelphij } 3243262685Sdelphij endwin(); /* End curses mode */ 3244262685Sdelphij return 0; 3245166124Srafan} 3246166124Srafanvoid init_win_params(WIN *p_win) 3247166124Srafan{ 3248262685Sdelphij p_win->height = 3; 3249262685Sdelphij p_win->width = 10; 3250262685Sdelphij p_win->starty = (LINES - p_win->height)/2; 3251262685Sdelphij p_win->startx = (COLS - p_win->width)/2; 3252166124Srafan 3253262685Sdelphij p_win->border.ls = '|'; 3254262685Sdelphij p_win->border.rs = '|'; 3255262685Sdelphij p_win->border.ts = '-'; 3256262685Sdelphij p_win->border.bs = '-'; 3257262685Sdelphij p_win->border.tl = '+'; 3258262685Sdelphij p_win->border.tr = '+'; 3259262685Sdelphij p_win->border.bl = '+'; 3260262685Sdelphij p_win->border.br = '+'; 3261166124Srafan 3262166124Srafan} 3263166124Srafanvoid print_win_params(WIN *p_win) 3264166124Srafan{ 3265166124Srafan#ifdef _DEBUG 3266262685Sdelphij mvprintw(25, 0, "%d %d %d %d", p_win->startx, p_win->starty, 3267262685Sdelphij p_win->width, p_win->height); 3268262685Sdelphij refresh(); 3269166124Srafan#endif 3270166124Srafan} 3271166124Srafanvoid create_box(WIN *p_win, bool flag) 3272262685Sdelphij{ int i, j; 3273262685Sdelphij int x, y, w, h; 3274166124Srafan 3275262685Sdelphij x = p_win->startx; 3276262685Sdelphij y = p_win->starty; 3277262685Sdelphij w = p_win->width; 3278262685Sdelphij h = p_win->height; 3279166124Srafan 3280262685Sdelphij if(flag == TRUE) 3281262685Sdelphij { mvaddch(y, x, p_win->border.tl); 3282262685Sdelphij mvaddch(y, x + w, p_win->border.tr); 3283262685Sdelphij mvaddch(y + h, x, p_win->border.bl); 3284262685Sdelphij mvaddch(y + h, x + w, p_win->border.br); 3285262685Sdelphij mvhline(y, x + 1, p_win->border.ts, w - 1); 3286262685Sdelphij mvhline(y + h, x + 1, p_win->border.bs, w - 1); 3287262685Sdelphij mvvline(y + 1, x, p_win->border.ls, h - 1); 3288262685Sdelphij mvvline(y + 1, x + w, p_win->border.rs, h - 1); 3289166124Srafan 3290262685Sdelphij } 3291262685Sdelphij else 3292262685Sdelphij for(j = y; j <= y + h; ++j) 3293262685Sdelphij for(i = x; i <= x + w; ++i) 3294262685Sdelphij mvaddch(j, i, ' '); 3295262685Sdelphij 3296262685Sdelphij refresh(); 3297166124Srafan 3298262685Sdelphij}</SPAN 3299262685Sdelphij></PRE 3300262685Sdelphij></DIV 3301262685Sdelphij></DIV 3302262685Sdelphij></DIV 3303262685Sdelphij><DIV 3304262685SdelphijCLASS="SECT1" 3305262685Sdelphij><HR><H2 3306262685SdelphijCLASS="SECT1" 3307262685Sdelphij><A 3308262685SdelphijNAME="COLOR" 3309262685Sdelphij>10. Colors</A 3310262685Sdelphij></H2 3311262685Sdelphij><DIV 3312262685SdelphijCLASS="SECT2" 3313262685Sdelphij><H3 3314262685SdelphijCLASS="SECT2" 3315262685Sdelphij><A 3316262685SdelphijNAME="COLORBASICS" 3317262685Sdelphij>10.1. The basics</A 3318262685Sdelphij></H3 3319262685Sdelphij><P 3320262685Sdelphij>Life seems dull with no colors. Curses has a nice mechanism to handle colors. 3321262685SdelphijLet's get into the thick of the things with a small program.</P 3322262685Sdelphij><DIV 3323262685SdelphijCLASS="EXAMPLE" 3324262685Sdelphij><A 3325262685SdelphijNAME="BSICO" 3326262685Sdelphij></A 3327262685Sdelphij><P 3328262685Sdelphij><B 3329262685Sdelphij>Example 9. A Simple Color example </B 3330262685Sdelphij></P 3331262685Sdelphij><PRE 3332262685SdelphijCLASS="PROGRAMLISTING" 3333262685Sdelphij><SPAN 3334262685SdelphijCLASS="INLINEMEDIAOBJECT" 3335262685Sdelphij>#include <ncurses.h> 3336166124Srafan 3337166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string); 3338166124Srafanint main(int argc, char *argv[]) 3339262685Sdelphij{ initscr(); /* Start curses mode */ 3340262685Sdelphij if(has_colors() == FALSE) 3341262685Sdelphij { endwin(); 3342262685Sdelphij printf("Your terminal does not support color\n"); 3343262685Sdelphij exit(1); 3344262685Sdelphij } 3345262685Sdelphij start_color(); /* Start color */ 3346262685Sdelphij init_pair(1, COLOR_RED, COLOR_BLACK); 3347166124Srafan 3348262685Sdelphij attron(COLOR_PAIR(1)); 3349262685Sdelphij print_in_middle(stdscr, LINES / 2, 0, 0, "Viola !!! In color ..."); 3350262685Sdelphij attroff(COLOR_PAIR(1)); 3351262685Sdelphij getch(); 3352262685Sdelphij endwin(); 3353166124Srafan} 3354166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string) 3355262685Sdelphij{ int length, x, y; 3356262685Sdelphij float temp; 3357166124Srafan 3358262685Sdelphij if(win == NULL) 3359262685Sdelphij win = stdscr; 3360262685Sdelphij getyx(win, y, x); 3361262685Sdelphij if(startx != 0) 3362262685Sdelphij x = startx; 3363262685Sdelphij if(starty != 0) 3364262685Sdelphij y = starty; 3365262685Sdelphij if(width == 0) 3366262685Sdelphij width = 80; 3367166124Srafan 3368262685Sdelphij length = strlen(string); 3369262685Sdelphij temp = (width - length)/ 2; 3370262685Sdelphij x = startx + (int)temp; 3371262685Sdelphij mvwprintw(win, y, x, "%s", string); 3372262685Sdelphij refresh(); 3373166124Srafan} 3374262685Sdelphij</SPAN 3375262685Sdelphij></PRE 3376262685Sdelphij></DIV 3377262685Sdelphij><P 3378262685Sdelphij>As you can see, to start using color, you should first call the function 3379262685Sdelphij<TT 3380262685SdelphijCLASS="LITERAL" 3381262685Sdelphij> start_color()</TT 3382262685Sdelphij>. After that, you can use color 3383262685Sdelphijcapabilities of your terminals using various functions. To find out whether a 3384262685Sdelphijterminal has color capabilities or not, you can use 3385262685Sdelphij<TT 3386262685SdelphijCLASS="LITERAL" 3387262685Sdelphij>has_colors()</TT 3388262685Sdelphij> function, which returns FALSE if 3389262685Sdelphijthe terminal does not support color. </P 3390262685Sdelphij><P 3391262685Sdelphij>Curses initializes all the colors supported by terminal when start_color() is 3392262685Sdelphijcalled. These can be accessed by the define constants like 3393262685Sdelphij<TT 3394262685SdelphijCLASS="LITERAL" 3395262685Sdelphij>COLOR_BLACK </TT 3396262685Sdelphij> etc. Now to actually start using 3397262685Sdelphijcolors, you have to define pairs. Colors are always used in pairs. That means 3398262685Sdelphijyou have to use the function <TT 3399262685SdelphijCLASS="LITERAL" 3400262685Sdelphij>init_pair() </TT 3401262685Sdelphij> to 3402262685Sdelphijdefine the foreground and background for the pair number you give. After that 3403262685Sdelphijthat pair number can be used as a normal attribute with <TT 3404262685SdelphijCLASS="LITERAL" 3405262685Sdelphij>COLOR_PAIR()</TT 3406262685Sdelphij>function. This may seem to be cumbersome at first. 3407262685SdelphijBut this elegant solution allows us to manage color pairs very easily. To 3408262685Sdelphijappreciate it, you have to look into the the source code of "dialog", a utility 3409262685Sdelphijfor displaying dialog boxes from shell scripts. The developers have defined 3410262685Sdelphijforeground and background combinations for all the colors they might need and 3411262685Sdelphijinitialized at the beginning. This makes it very easy to set attributes just by 3412262685Sdelphijaccessing a pair which we already have defined as a constant.</P 3413262685Sdelphij><P 3414262685Sdelphij>The following colors are defined in <TT 3415262685SdelphijCLASS="LITERAL" 3416262685Sdelphij>curses.h</TT 3417262685Sdelphij>. 3418262685SdelphijYou can use these as parameters for various color functions. 3419262685Sdelphij<PRE 3420262685SdelphijCLASS="PROGRAMLISTING" 3421262685Sdelphij> COLOR_BLACK 0 3422166124Srafan COLOR_RED 1 3423166124Srafan COLOR_GREEN 2 3424166124Srafan COLOR_YELLOW 3 3425166124Srafan COLOR_BLUE 4 3426166124Srafan COLOR_MAGENTA 5 3427166124Srafan COLOR_CYAN 6 3428262685Sdelphij COLOR_WHITE 7</PRE 3429262685Sdelphij></P 3430262685Sdelphij></DIV 3431262685Sdelphij><DIV 3432262685SdelphijCLASS="SECT2" 3433262685Sdelphij><HR><H3 3434262685SdelphijCLASS="SECT2" 3435262685Sdelphij><A 3436262685SdelphijNAME="CHANGECOLORDEFS" 3437262685Sdelphij>10.2. Changing Color Definitions</A 3438262685Sdelphij></H3 3439262685Sdelphij><P 3440262685Sdelphij>The function <TT 3441262685SdelphijCLASS="LITERAL" 3442262685Sdelphij>init_color()</TT 3443262685Sdelphij>can be used to change 3444262685Sdelphijthe rgb values for the colors defined by curses initially. Say you wanted to 3445262685Sdelphijlighten the intensity of red color by a minuscule. Then you can use this 3446262685Sdelphijfunction as</P 3447262685Sdelphij><PRE 3448262685SdelphijCLASS="PROGRAMLISTING" 3449262685Sdelphij> init_color(COLOR_RED, 700, 0, 0); 3450166124Srafan /* param 1 : color name 3451262685Sdelphij * param 2, 3, 4 : rgb content min = 0, max = 1000 */</PRE 3452262685Sdelphij><P 3453262685Sdelphij>If your terminal cannot change the color definitions, the function returns ERR. 3454262685SdelphijThe function <TT 3455262685SdelphijCLASS="LITERAL" 3456262685Sdelphij>can_change_color()</TT 3457262685Sdelphij> can be used to 3458262685Sdelphijfind out whether the terminal has the capability of changing color content or 3459262685Sdelphijnot. The rgb content is scaled from 0 to 1000. Initially RED color is defined 3460262685Sdelphijwith content 1000(r), 0(g), 0(b). </P 3461262685Sdelphij></DIV 3462262685Sdelphij><DIV 3463262685SdelphijCLASS="SECT2" 3464262685Sdelphij><HR><H3 3465262685SdelphijCLASS="SECT2" 3466262685Sdelphij><A 3467262685SdelphijNAME="COLORCONTENT" 3468262685Sdelphij>10.3. Color Content</A 3469262685Sdelphij></H3 3470262685Sdelphij><P 3471262685Sdelphij>The functions <TT 3472262685SdelphijCLASS="LITERAL" 3473262685Sdelphij>color_content()</TT 3474262685Sdelphij> and 3475262685Sdelphij<TT 3476262685SdelphijCLASS="LITERAL" 3477262685Sdelphij>pair_content()</TT 3478262685Sdelphij> can be used to find the color 3479262685Sdelphijcontent and foreground, background combination for the pair. </P 3480262685Sdelphij></DIV 3481262685Sdelphij></DIV 3482262685Sdelphij><DIV 3483262685SdelphijCLASS="SECT1" 3484262685Sdelphij><HR><H2 3485262685SdelphijCLASS="SECT1" 3486262685Sdelphij><A 3487262685SdelphijNAME="KEYS" 3488262685Sdelphij>11. Interfacing with the key board</A 3489262685Sdelphij></H2 3490262685Sdelphij><DIV 3491262685SdelphijCLASS="SECT2" 3492262685Sdelphij><H3 3493262685SdelphijCLASS="SECT2" 3494262685Sdelphij><A 3495262685SdelphijNAME="KEYSBASICS" 3496262685Sdelphij>11.1. The Basics</A 3497262685Sdelphij></H3 3498262685Sdelphij><P 3499262685Sdelphij>No GUI is complete without a strong user interface and to interact with the 3500262685Sdelphijuser, a curses program should be sensitive to key presses or the mouse actions 3501262685Sdelphijdone by the user. Let's deal with the keys first.</P 3502262685Sdelphij><P 3503262685Sdelphij>As you have seen in almost all of the above examples, it's very easy to get key 3504262685Sdelphijinput from the user. A simple way of getting key presses is to use 3505262685Sdelphij<TT 3506262685SdelphijCLASS="LITERAL" 3507262685Sdelphij>getch()</TT 3508262685Sdelphij> function. The cbreak mode should be 3509262685Sdelphijenabled to read keys when you are interested in reading individual key hits 3510262685Sdelphijrather than complete lines of text (which usually end with a carriage return). 3511262685Sdelphijkeypad should be enabled to get the Functions keys, arrow keys etc. See the 3512262685Sdelphijinitialization section for details.</P 3513262685Sdelphij><P 3514262685Sdelphij><TT 3515262685SdelphijCLASS="LITERAL" 3516262685Sdelphij>getch()</TT 3517262685Sdelphij> returns an integer corresponding to the 3518262685Sdelphijkey pressed. If it is a normal character, the integer value will be equivalent 3519262685Sdelphijto the character. Otherwise it returns a number which can be matched with the 3520262685Sdelphijconstants defined in <TT 3521262685SdelphijCLASS="LITERAL" 3522262685Sdelphij>curses.h</TT 3523262685Sdelphij>. For example if 3524262685Sdelphijthe user presses F1, the integer returned is 265. This can be checked using the 3525262685Sdelphijmacro KEY_F() defined in curses.h. This makes reading keys portable and easy to 3526262685Sdelphijmanage.</P 3527262685Sdelphij><P 3528262685Sdelphij>For example, if you call getch() like this</P 3529262685Sdelphij><PRE 3530262685SdelphijCLASS="PROGRAMLISTING" 3531262685Sdelphij> int ch; 3532166124Srafan 3533262685Sdelphij ch = getch();</PRE 3534262685Sdelphij><P 3535262685Sdelphij>getch() will wait for the user to press a key, (unless you specified a timeout) 3536262685Sdelphijand when user presses a key, the corresponding integer is returned. Then you can 3537262685Sdelphijcheck the value returned with the constants defined in curses.h to match against 3538262685Sdelphijthe keys you want.</P 3539262685Sdelphij><P 3540262685Sdelphij>The following code piece will do that job.</P 3541262685Sdelphij><PRE 3542262685SdelphijCLASS="PROGRAMLISTING" 3543262685Sdelphij> if(ch == KEY_LEFT) 3544262685Sdelphij printw("Left arrow is pressed\n");</PRE 3545262685Sdelphij><P 3546262685Sdelphij>Let's write a small program which creates a menu which can be navigated by up 3547262685Sdelphijand down arrows.</P 3548262685Sdelphij></DIV 3549262685Sdelphij><DIV 3550262685SdelphijCLASS="SECT2" 3551262685Sdelphij><HR><H3 3552262685SdelphijCLASS="SECT2" 3553262685Sdelphij><A 3554262685SdelphijNAME="SIMPLEKEYEX" 3555262685Sdelphij>11.2. A Simple Key Usage example</A 3556262685Sdelphij></H3 3557262685Sdelphij><DIV 3558262685SdelphijCLASS="EXAMPLE" 3559262685Sdelphij><A 3560262685SdelphijNAME="BSIKE" 3561262685Sdelphij></A 3562262685Sdelphij><P 3563262685Sdelphij><B 3564262685Sdelphij>Example 10. A Simple Key Usage example </B 3565262685Sdelphij></P 3566262685Sdelphij><PRE 3567262685SdelphijCLASS="PROGRAMLISTING" 3568262685Sdelphij><SPAN 3569262685SdelphijCLASS="INLINEMEDIAOBJECT" 3570262685Sdelphij>#include <stdio.h> 3571262685Sdelphij#include <ncurses.h> 3572166124Srafan 3573166124Srafan#define WIDTH 30 3574166124Srafan#define HEIGHT 10 3575166124Srafan 3576166124Srafanint startx = 0; 3577166124Srafanint starty = 0; 3578166124Srafan 3579166124Srafanchar *choices[] = { 3580262685Sdelphij "Choice 1", 3581262685Sdelphij "Choice 2", 3582262685Sdelphij "Choice 3", 3583262685Sdelphij "Choice 4", 3584262685Sdelphij "Exit", 3585262685Sdelphij }; 3586166124Srafanint n_choices = sizeof(choices) / sizeof(char *); 3587166124Srafanvoid print_menu(WINDOW *menu_win, int highlight); 3588166124Srafan 3589166124Srafanint main() 3590262685Sdelphij{ WINDOW *menu_win; 3591262685Sdelphij int highlight = 1; 3592262685Sdelphij int choice = 0; 3593262685Sdelphij int c; 3594166124Srafan 3595262685Sdelphij initscr(); 3596262685Sdelphij clear(); 3597262685Sdelphij noecho(); 3598262685Sdelphij cbreak(); /* Line buffering disabled. pass on everything */ 3599262685Sdelphij startx = (80 - WIDTH) / 2; 3600262685Sdelphij starty = (24 - HEIGHT) / 2; 3601262685Sdelphij 3602262685Sdelphij menu_win = newwin(HEIGHT, WIDTH, starty, startx); 3603262685Sdelphij keypad(menu_win, TRUE); 3604262685Sdelphij mvprintw(0, 0, "Use arrow keys to go up and down, Press enter to select a choice"); 3605262685Sdelphij refresh(); 3606262685Sdelphij print_menu(menu_win, highlight); 3607262685Sdelphij while(1) 3608262685Sdelphij { c = wgetch(menu_win); 3609262685Sdelphij switch(c) 3610262685Sdelphij { case KEY_UP: 3611262685Sdelphij if(highlight == 1) 3612262685Sdelphij highlight = n_choices; 3613262685Sdelphij else 3614262685Sdelphij --highlight; 3615262685Sdelphij break; 3616262685Sdelphij case KEY_DOWN: 3617262685Sdelphij if(highlight == n_choices) 3618262685Sdelphij highlight = 1; 3619262685Sdelphij else 3620262685Sdelphij ++highlight; 3621262685Sdelphij break; 3622262685Sdelphij case 10: 3623262685Sdelphij choice = highlight; 3624262685Sdelphij break; 3625262685Sdelphij default: 3626262685Sdelphij mvprintw(24, 0, "Charcter pressed is = %3d Hopefully it can be printed as '%c'", c, c); 3627262685Sdelphij refresh(); 3628262685Sdelphij break; 3629262685Sdelphij } 3630262685Sdelphij print_menu(menu_win, highlight); 3631262685Sdelphij if(choice != 0) /* User did a choice come out of the infinite loop */ 3632262685Sdelphij break; 3633262685Sdelphij } 3634262685Sdelphij mvprintw(23, 0, "You chose choice %d with choice string %s\n", choice, choices[choice - 1]); 3635262685Sdelphij clrtoeol(); 3636262685Sdelphij refresh(); 3637262685Sdelphij endwin(); 3638262685Sdelphij return 0; 3639166124Srafan} 3640166124Srafan 3641166124Srafan 3642166124Srafanvoid print_menu(WINDOW *menu_win, int highlight) 3643166124Srafan{ 3644262685Sdelphij int x, y, i; 3645166124Srafan 3646262685Sdelphij x = 2; 3647262685Sdelphij y = 2; 3648262685Sdelphij box(menu_win, 0, 0); 3649262685Sdelphij for(i = 0; i < n_choices; ++i) 3650262685Sdelphij { if(highlight == i + 1) /* High light the present choice */ 3651262685Sdelphij { wattron(menu_win, A_REVERSE); 3652262685Sdelphij mvwprintw(menu_win, y, x, "%s", choices[i]); 3653262685Sdelphij wattroff(menu_win, A_REVERSE); 3654262685Sdelphij } 3655262685Sdelphij else 3656262685Sdelphij mvwprintw(menu_win, y, x, "%s", choices[i]); 3657262685Sdelphij ++y; 3658262685Sdelphij } 3659262685Sdelphij wrefresh(menu_win); 3660166124Srafan} 3661262685Sdelphij</SPAN 3662262685Sdelphij></PRE 3663262685Sdelphij></DIV 3664262685Sdelphij></DIV 3665262685Sdelphij></DIV 3666262685Sdelphij><DIV 3667262685SdelphijCLASS="SECT1" 3668262685Sdelphij><HR><H2 3669262685SdelphijCLASS="SECT1" 3670262685Sdelphij><A 3671262685SdelphijNAME="MOUSE" 3672262685Sdelphij>12. Interfacing with the mouse</A 3673262685Sdelphij></H2 3674262685Sdelphij><P 3675262685Sdelphij>Now that you have seen how to get keys, lets do the same thing from mouse. 3676262685SdelphijUsually each UI allows the user to interact with both keyboard and mouse. </P 3677262685Sdelphij><DIV 3678262685SdelphijCLASS="SECT2" 3679262685Sdelphij><HR><H3 3680262685SdelphijCLASS="SECT2" 3681262685Sdelphij><A 3682262685SdelphijNAME="MOUSEBASICS" 3683262685Sdelphij>12.1. The Basics</A 3684262685Sdelphij></H3 3685262685Sdelphij><P 3686262685Sdelphij>Before you do any thing else, the events you want to receive have to be enabled 3687262685Sdelphijwith <TT 3688262685SdelphijCLASS="LITERAL" 3689262685Sdelphij>mousemask()</TT 3690262685Sdelphij>.</P 3691262685Sdelphij><PRE 3692262685SdelphijCLASS="PROGRAMLISTING" 3693262685Sdelphij> mousemask( mmask_t newmask, /* The events you want to listen to */ 3694262685Sdelphij mmask_t *oldmask) /* The old events mask */</PRE 3695262685Sdelphij><P 3696262685Sdelphij>The first parameter to above function is a bit mask of events you would like to 3697262685Sdelphijlisten. By default, all the events are turned off. The bit mask <TT 3698262685SdelphijCLASS="LITERAL" 3699262685Sdelphij> ALL_MOUSE_EVENTS</TT 3700262685Sdelphij> can be used to get all the events.</P 3701262685Sdelphij><P 3702262685Sdelphij>The following are all the event masks:</P 3703262685Sdelphij><PRE 3704262685SdelphijCLASS="PROGRAMLISTING" 3705262685Sdelphij> Name Description 3706166124Srafan --------------------------------------------------------------------- 3707166124Srafan BUTTON1_PRESSED mouse button 1 down 3708166124Srafan BUTTON1_RELEASED mouse button 1 up 3709166124Srafan BUTTON1_CLICKED mouse button 1 clicked 3710166124Srafan BUTTON1_DOUBLE_CLICKED mouse button 1 double clicked 3711166124Srafan BUTTON1_TRIPLE_CLICKED mouse button 1 triple clicked 3712166124Srafan BUTTON2_PRESSED mouse button 2 down 3713166124Srafan BUTTON2_RELEASED mouse button 2 up 3714166124Srafan BUTTON2_CLICKED mouse button 2 clicked 3715166124Srafan BUTTON2_DOUBLE_CLICKED mouse button 2 double clicked 3716166124Srafan BUTTON2_TRIPLE_CLICKED mouse button 2 triple clicked 3717166124Srafan BUTTON3_PRESSED mouse button 3 down 3718166124Srafan BUTTON3_RELEASED mouse button 3 up 3719166124Srafan BUTTON3_CLICKED mouse button 3 clicked 3720166124Srafan BUTTON3_DOUBLE_CLICKED mouse button 3 double clicked 3721166124Srafan BUTTON3_TRIPLE_CLICKED mouse button 3 triple clicked 3722166124Srafan BUTTON4_PRESSED mouse button 4 down 3723166124Srafan BUTTON4_RELEASED mouse button 4 up 3724166124Srafan BUTTON4_CLICKED mouse button 4 clicked 3725166124Srafan BUTTON4_DOUBLE_CLICKED mouse button 4 double clicked 3726166124Srafan BUTTON4_TRIPLE_CLICKED mouse button 4 triple clicked 3727166124Srafan BUTTON_SHIFT shift was down during button state change 3728166124Srafan BUTTON_CTRL control was down during button state change 3729166124Srafan BUTTON_ALT alt was down during button state change 3730166124Srafan ALL_MOUSE_EVENTS report all button state changes 3731262685Sdelphij REPORT_MOUSE_POSITION report mouse movement</PRE 3732262685Sdelphij></DIV 3733262685Sdelphij><DIV 3734262685SdelphijCLASS="SECT2" 3735262685Sdelphij><HR><H3 3736262685SdelphijCLASS="SECT2" 3737262685Sdelphij><A 3738262685SdelphijNAME="GETTINGEVENTS" 3739262685Sdelphij>12.2. Getting the events</A 3740262685Sdelphij></H3 3741262685Sdelphij><P 3742262685Sdelphij>Once a class of mouse events have been enabled, getch() class of functions 3743262685Sdelphijreturn KEY_MOUSE every time some mouse event happens. Then the mouse event can 3744262685Sdelphijbe retrieved with <TT 3745262685SdelphijCLASS="LITERAL" 3746262685Sdelphij>getmouse()</TT 3747262685Sdelphij>.</P 3748262685Sdelphij><P 3749262685Sdelphij>The code approximately looks like this:</P 3750262685Sdelphij><PRE 3751262685SdelphijCLASS="PROGRAMLISTING" 3752262685Sdelphij> MEVENT event; 3753166124Srafan 3754166124Srafan ch = getch(); 3755166124Srafan if(ch == KEY_MOUSE) 3756166124Srafan if(getmouse(&event) == OK) 3757166124Srafan . /* Do some thing with the event */ 3758166124Srafan . 3759262685Sdelphij .</PRE 3760262685Sdelphij><P 3761262685Sdelphij> 3762262685Sdelphijgetmouse() returns the event into the pointer given to it. It's a structure 3763262685Sdelphijwhich contains</P 3764262685Sdelphij><PRE 3765262685SdelphijCLASS="PROGRAMLISTING" 3766262685Sdelphij> typedef struct 3767166124Srafan { 3768166124Srafan short id; /* ID to distinguish multiple devices */ 3769166124Srafan int x, y, z; /* event coordinates */ 3770166124Srafan mmask_t bstate; /* button state bits */ 3771262685Sdelphij } </PRE 3772262685Sdelphij><P 3773262685Sdelphij>The <TT 3774262685SdelphijCLASS="LITERAL" 3775262685Sdelphij>bstate</TT 3776262685Sdelphij> is the main variable we are 3777262685Sdelphijinterested in. It tells the button state of the mouse.</P 3778262685Sdelphij><P 3779262685Sdelphij>Then with a code snippet like the following, we can find out what happened.</P 3780262685Sdelphij><PRE 3781262685SdelphijCLASS="PROGRAMLISTING" 3782262685Sdelphij> if(event.bstate & BUTTON1_PRESSED) 3783262685Sdelphij printw("Left Button Pressed");</PRE 3784262685Sdelphij></DIV 3785262685Sdelphij><DIV 3786262685SdelphijCLASS="SECT2" 3787262685Sdelphij><HR><H3 3788262685SdelphijCLASS="SECT2" 3789262685Sdelphij><A 3790262685SdelphijNAME="MOUSETOGETHER" 3791262685Sdelphij>12.3. Putting it all Together</A 3792262685Sdelphij></H3 3793262685Sdelphij><P 3794262685Sdelphij>That's pretty much interfacing with mouse. Let's create the same menu and enable 3795262685Sdelphijmouse interaction. To make things simpler, key handling is removed.</P 3796262685Sdelphij><DIV 3797262685SdelphijCLASS="EXAMPLE" 3798262685Sdelphij><A 3799262685SdelphijNAME="BMOME" 3800262685Sdelphij></A 3801262685Sdelphij><P 3802262685Sdelphij><B 3803262685Sdelphij>Example 11. Access the menu with mouse !!! </B 3804262685Sdelphij></P 3805262685Sdelphij><PRE 3806262685SdelphijCLASS="PROGRAMLISTING" 3807262685Sdelphij><SPAN 3808262685SdelphijCLASS="INLINEMEDIAOBJECT" 3809262685Sdelphij>#include <ncurses.h> 3810166124Srafan 3811166124Srafan#define WIDTH 30 3812166124Srafan#define HEIGHT 10 3813166124Srafan 3814166124Srafanint startx = 0; 3815166124Srafanint starty = 0; 3816166124Srafan 3817262685Sdelphijchar *choices[] = { "Choice 1", 3818262685Sdelphij "Choice 2", 3819262685Sdelphij "Choice 3", 3820262685Sdelphij "Choice 4", 3821262685Sdelphij "Exit", 3822262685Sdelphij }; 3823166124Srafan 3824166124Srafanint n_choices = sizeof(choices) / sizeof(char *); 3825166124Srafan 3826166124Srafanvoid print_menu(WINDOW *menu_win, int highlight); 3827166124Srafanvoid report_choice(int mouse_x, int mouse_y, int *p_choice); 3828166124Srafan 3829166124Srafanint main() 3830262685Sdelphij{ int c, choice = 0; 3831262685Sdelphij WINDOW *menu_win; 3832262685Sdelphij MEVENT event; 3833166124Srafan 3834262685Sdelphij /* Initialize curses */ 3835262685Sdelphij initscr(); 3836262685Sdelphij clear(); 3837262685Sdelphij noecho(); 3838262685Sdelphij cbreak(); //Line buffering disabled. pass on everything 3839166124Srafan 3840262685Sdelphij /* Try to put the window in the middle of screen */ 3841262685Sdelphij startx = (80 - WIDTH) / 2; 3842262685Sdelphij starty = (24 - HEIGHT) / 2; 3843262685Sdelphij 3844262685Sdelphij attron(A_REVERSE); 3845262685Sdelphij mvprintw(23, 1, "Click on Exit to quit (Works best in a virtual console)"); 3846262685Sdelphij refresh(); 3847262685Sdelphij attroff(A_REVERSE); 3848166124Srafan 3849262685Sdelphij /* Print the menu for the first time */ 3850262685Sdelphij menu_win = newwin(HEIGHT, WIDTH, starty, startx); 3851262685Sdelphij print_menu(menu_win, 1); 3852262685Sdelphij /* Get all the mouse events */ 3853262685Sdelphij mousemask(ALL_MOUSE_EVENTS, NULL); 3854262685Sdelphij 3855262685Sdelphij while(1) 3856262685Sdelphij { c = wgetch(menu_win); 3857262685Sdelphij switch(c) 3858262685Sdelphij { case KEY_MOUSE: 3859262685Sdelphij if(getmouse(&event) == OK) 3860262685Sdelphij { /* When the user clicks left mouse button */ 3861262685Sdelphij if(event.bstate & BUTTON1_PRESSED) 3862262685Sdelphij { report_choice(event.x + 1, event.y + 1, &choice); 3863262685Sdelphij if(choice == -1) //Exit chosen 3864262685Sdelphij goto end; 3865262685Sdelphij mvprintw(22, 1, "Choice made is : %d String Chosen is \"%10s\"", choice, choices[choice - 1]); 3866262685Sdelphij refresh(); 3867262685Sdelphij } 3868262685Sdelphij } 3869262685Sdelphij print_menu(menu_win, choice); 3870262685Sdelphij break; 3871262685Sdelphij } 3872262685Sdelphij } 3873166124Srafanend: 3874262685Sdelphij endwin(); 3875262685Sdelphij return 0; 3876166124Srafan} 3877166124Srafan 3878166124Srafan 3879166124Srafanvoid print_menu(WINDOW *menu_win, int highlight) 3880166124Srafan{ 3881262685Sdelphij int x, y, i; 3882166124Srafan 3883262685Sdelphij x = 2; 3884262685Sdelphij y = 2; 3885262685Sdelphij box(menu_win, 0, 0); 3886262685Sdelphij for(i = 0; i < n_choices; ++i) 3887262685Sdelphij { if(highlight == i + 1) 3888262685Sdelphij { wattron(menu_win, A_REVERSE); 3889262685Sdelphij mvwprintw(menu_win, y, x, "%s", choices[i]); 3890262685Sdelphij wattroff(menu_win, A_REVERSE); 3891262685Sdelphij } 3892262685Sdelphij else 3893262685Sdelphij mvwprintw(menu_win, y, x, "%s", choices[i]); 3894262685Sdelphij ++y; 3895262685Sdelphij } 3896262685Sdelphij wrefresh(menu_win); 3897166124Srafan} 3898166124Srafan 3899166124Srafan/* Report the choice according to mouse position */ 3900166124Srafanvoid report_choice(int mouse_x, int mouse_y, int *p_choice) 3901262685Sdelphij{ int i,j, choice; 3902166124Srafan 3903262685Sdelphij i = startx + 2; 3904262685Sdelphij j = starty + 3; 3905262685Sdelphij 3906262685Sdelphij for(choice = 0; choice < n_choices; ++choice) 3907262685Sdelphij if(mouse_y == j + choice && mouse_x >= i && mouse_x <= i + strlen(choices[choice])) 3908262685Sdelphij { if(choice == n_choices - 1) 3909262685Sdelphij *p_choice = -1; 3910262685Sdelphij else 3911262685Sdelphij *p_choice = choice + 1; 3912262685Sdelphij break; 3913262685Sdelphij } 3914262685Sdelphij}</SPAN 3915262685Sdelphij></PRE 3916262685Sdelphij></DIV 3917262685Sdelphij></DIV 3918262685Sdelphij><DIV 3919262685SdelphijCLASS="SECT2" 3920262685Sdelphij><HR><H3 3921262685SdelphijCLASS="SECT2" 3922262685Sdelphij><A 3923262685SdelphijNAME="MISCMOUSEFUNCS" 3924262685Sdelphij>12.4. Miscellaneous Functions</A 3925262685Sdelphij></H3 3926262685Sdelphij><P 3927262685Sdelphij>The functions mouse_trafo() and wmouse_trafo() can be used to convert to mouse 3928262685Sdelphijco-ordinates to screen relative co-ordinates. See curs_mouse(3X) man page for details.</P 3929262685Sdelphij><P 3930262685Sdelphij>The mouseinterval function sets the maximum time (in thousands of a 3931262685Sdelphijsecond) that can elapse between press and release events in order for 3932262685Sdelphijthem to be recognized as a click. This function returns the previous 3933262685Sdelphijinterval value. The default is one fifth of a second.</P 3934262685Sdelphij></DIV 3935262685Sdelphij></DIV 3936262685Sdelphij><DIV 3937262685SdelphijCLASS="SECT1" 3938262685Sdelphij><HR><H2 3939262685SdelphijCLASS="SECT1" 3940262685Sdelphij><A 3941262685SdelphijNAME="SCREEN" 3942262685Sdelphij>13. Screen Manipulation</A 3943262685Sdelphij></H2 3944262685Sdelphij><P 3945262685Sdelphij>In this section, we will look into some functions, which allow us to manage the 3946262685Sdelphijscreen efficiently and to write some fancy programs. This is especially 3947262685Sdelphijimportant in writing games. </P 3948262685Sdelphij><DIV 3949262685SdelphijCLASS="SECT2" 3950262685Sdelphij><HR><H3 3951262685SdelphijCLASS="SECT2" 3952262685Sdelphij><A 3953262685SdelphijNAME="GETYX" 3954262685Sdelphij>13.1. getyx() functions</A 3955262685Sdelphij></H3 3956262685Sdelphij><P 3957262685Sdelphij> The function <TT 3958262685SdelphijCLASS="LITERAL" 3959262685Sdelphij>getyx()</TT 3960262685Sdelphij> can be used to find out 3961262685Sdelphijthe present cursor co-ordinates. It will fill the values of x and y co-ordinates 3962262685Sdelphijin the arguments given to it. Since getyx() is a macro you don't have to pass 3963262685Sdelphijthe address of the variables. It can be called as</P 3964262685Sdelphij><PRE 3965262685SdelphijCLASS="PROGRAMLISTING" 3966262685Sdelphij> getyx(win, y, x); 3967166124Srafan /* win: window pointer 3968166124Srafan * y, x: y, x co-ordinates will be put into this variables 3969262685Sdelphij */</PRE 3970262685Sdelphij><P 3971262685Sdelphij>The function getparyx() gets the beginning co-ordinates of the sub window 3972262685Sdelphijrelative to the main window. This is some times useful to update a sub window. 3973262685SdelphijWhen designing fancy stuff like writing multiple menus, it becomes difficult to 3974262685Sdelphijstore the menu positions, their first option co-ordinates etc. A simple solution 3975262685Sdelphijto this problem, is to create menus in sub windows and later find the starting 3976262685Sdelphijco-ordinates of the menus by using getparyx().</P 3977262685Sdelphij><P 3978262685Sdelphij>The functions getbegyx() and getmaxyx() store current window's beginning and 3979262685Sdelphijmaximum co-ordinates. These functions are useful in the same way as above in 3980262685Sdelphijmanaging the windows and sub windows effectively.</P 3981262685Sdelphij></DIV 3982262685Sdelphij><DIV 3983262685SdelphijCLASS="SECT2" 3984262685Sdelphij><HR><H3 3985262685SdelphijCLASS="SECT2" 3986262685Sdelphij><A 3987262685SdelphijNAME="SCREENDUMP" 3988262685Sdelphij>13.2. Screen Dumping</A 3989262685Sdelphij></H3 3990262685Sdelphij><P 3991262685Sdelphij>While writing games, some times it becomes necessary to store the state of the 3992262685Sdelphijscreen and restore it back to the same state. The function scr_dump() can be 3993262685Sdelphijused to dump the screen contents to a file given as an argument. Later it can be 3994262685Sdelphijrestored by scr_restore function. These two simple functions can be used 3995262685Sdelphijeffectively to maintain a fast moving game with changing scenarios. </P 3996262685Sdelphij></DIV 3997262685Sdelphij><DIV 3998262685SdelphijCLASS="SECT2" 3999262685Sdelphij><HR><H3 4000262685SdelphijCLASS="SECT2" 4001262685Sdelphij><A 4002262685SdelphijNAME="WINDOWDUMP" 4003262685Sdelphij>13.3. Window Dumping</A 4004262685Sdelphij></H3 4005262685Sdelphij><P 4006262685Sdelphij>To store and restore windows, the functions 4007262685Sdelphij<TT 4008262685SdelphijCLASS="LITERAL" 4009262685Sdelphij>putwin()</TT 4010262685Sdelphij> and <TT 4011262685SdelphijCLASS="LITERAL" 4012262685Sdelphij>getwin()</TT 4013262685Sdelphij> can be used. <TT 4014262685SdelphijCLASS="LITERAL" 4015262685Sdelphij>putwin()</TT 4016262685Sdelphij> puts 4017262685Sdelphijthe present window state into a file, which can be later restored by 4018262685Sdelphij<TT 4019262685SdelphijCLASS="LITERAL" 4020262685Sdelphij>getwin()</TT 4021262685Sdelphij>.</P 4022262685Sdelphij><P 4023262685Sdelphij> 4024262685SdelphijThe function <TT 4025262685SdelphijCLASS="LITERAL" 4026262685Sdelphij>copywin()</TT 4027262685Sdelphij> can be used to copy a 4028262685Sdelphijwindow completely onto another window. It takes the source and destination 4029262685Sdelphijwindows as parameters and according to the rectangle specified, it copies the 4030262685Sdelphijrectangular region from source to destination window. It's last parameter 4031262685Sdelphijspecifies whether to overwrite or just overlay the contents on to the 4032262685Sdelphijdestination window. If this argument is true, then the copying is 4033262685Sdelphijnon-destructive.</P 4034262685Sdelphij></DIV 4035262685Sdelphij></DIV 4036262685Sdelphij><DIV 4037262685SdelphijCLASS="SECT1" 4038262685Sdelphij><HR><H2 4039262685SdelphijCLASS="SECT1" 4040262685Sdelphij><A 4041262685SdelphijNAME="MISC" 4042262685Sdelphij>14. Miscellaneous features</A 4043262685Sdelphij></H2 4044262685Sdelphij><P 4045262685Sdelphij>Now you know enough features to write a good curses program, with all bells and 4046262685Sdelphijwhistles. There are some miscellaneous functions which are useful in various 4047262685Sdelphijcases. Let's go headlong into some of those.</P 4048262685Sdelphij><DIV 4049262685SdelphijCLASS="SECT2" 4050262685Sdelphij><HR><H3 4051262685SdelphijCLASS="SECT2" 4052262685Sdelphij><A 4053262685SdelphijNAME="CURSSET" 4054262685Sdelphij>14.1. curs_set()</A 4055262685Sdelphij></H3 4056262685Sdelphij><P 4057262685Sdelphij>This function can be used to make the cursor invisible. The parameter to this 4058262685Sdelphijfunction should be </P 4059262685Sdelphij><PRE 4060262685SdelphijCLASS="PROGRAMLISTING" 4061262685Sdelphij> 0 : invisible or 4062166124Srafan 1 : normal or 4063262685Sdelphij 2 : very visible.</PRE 4064262685Sdelphij></DIV 4065262685Sdelphij><DIV 4066262685SdelphijCLASS="SECT2" 4067262685Sdelphij><HR><H3 4068262685SdelphijCLASS="SECT2" 4069262685Sdelphij><A 4070262685SdelphijNAME="TEMPLEAVE" 4071262685Sdelphij>14.2. Temporarily Leaving Curses mode</A 4072262685Sdelphij></H3 4073262685Sdelphij><P 4074262685Sdelphij>Some times you may want to get back to cooked mode (normal line buffering mode) 4075262685Sdelphijtemporarily. In such a case you will first need to save the tty modes with a 4076262685Sdelphijcall to <TT 4077262685SdelphijCLASS="LITERAL" 4078262685Sdelphij>def_prog_mode()</TT 4079262685Sdelphij> and then call 4080262685Sdelphij<TT 4081262685SdelphijCLASS="LITERAL" 4082262685Sdelphij>endwin()</TT 4083262685Sdelphij> to end the curses mode. This will 4084262685Sdelphijleave you in the original tty mode. To get back to curses once you are done, 4085262685Sdelphijcall <TT 4086262685SdelphijCLASS="LITERAL" 4087262685Sdelphij>reset_prog_mode() </TT 4088262685Sdelphij>. This function returns 4089262685Sdelphijthe tty to the state stored by <TT 4090262685SdelphijCLASS="LITERAL" 4091262685Sdelphij>def_prog_mode()</TT 4092262685Sdelphij>. Then do refresh(), and you are back to the curses mode. Here 4093262685Sdelphijis an example showing the sequence of things to be done.</P 4094262685Sdelphij><DIV 4095262685SdelphijCLASS="EXAMPLE" 4096262685Sdelphij><A 4097262685SdelphijNAME="BTELE" 4098262685Sdelphij></A 4099262685Sdelphij><P 4100262685Sdelphij><B 4101262685Sdelphij>Example 12. Temporarily Leaving Curses Mode </B 4102262685Sdelphij></P 4103262685Sdelphij><PRE 4104262685SdelphijCLASS="PROGRAMLISTING" 4105262685Sdelphij><SPAN 4106262685SdelphijCLASS="INLINEMEDIAOBJECT" 4107262685Sdelphij>#include <ncurses.h> 4108166124Srafan 4109166124Srafanint main() 4110262685Sdelphij{ 4111262685Sdelphij initscr(); /* Start curses mode */ 4112262685Sdelphij printw("Hello World !!!\n"); /* Print Hello World */ 4113262685Sdelphij refresh(); /* Print it on to the real screen */ 4114262685Sdelphij def_prog_mode(); /* Save the tty modes */ 4115262685Sdelphij endwin(); /* End curses mode temporarily */ 4116262685Sdelphij system("/bin/sh"); /* Do whatever you like in cooked mode */ 4117262685Sdelphij reset_prog_mode(); /* Return to the previous tty mode*/ 4118262685Sdelphij /* stored by def_prog_mode() */ 4119262685Sdelphij refresh(); /* Do refresh() to restore the */ 4120262685Sdelphij /* Screen contents */ 4121262685Sdelphij printw("Another String\n"); /* Back to curses use the full */ 4122262685Sdelphij refresh(); /* capabilities of curses */ 4123262685Sdelphij endwin(); /* End curses mode */ 4124166124Srafan 4125262685Sdelphij return 0; 4126262685Sdelphij}</SPAN 4127262685Sdelphij></PRE 4128262685Sdelphij></DIV 4129262685Sdelphij></DIV 4130262685Sdelphij><DIV 4131262685SdelphijCLASS="SECT2" 4132262685Sdelphij><HR><H3 4133262685SdelphijCLASS="SECT2" 4134262685Sdelphij><A 4135262685SdelphijNAME="ACSVARS" 4136262685Sdelphij>14.3. ACS_ variables</A 4137262685Sdelphij></H3 4138262685Sdelphij><P 4139262685Sdelphij>If you have ever programmed in DOS, you know about those nifty characters in 4140262685Sdelphijextended character set. They are printable only on some terminals. NCURSES 4141262685Sdelphijfunctions like <TT 4142262685SdelphijCLASS="LITERAL" 4143262685Sdelphij>box()</TT 4144262685Sdelphij> use these characters. All 4145262685Sdelphijthese variables start with ACS meaning alternative character set. You might have 4146262685Sdelphijnoticed me using these characters in some of the programs above. Here's an example 4147262685Sdelphijshowing all the characters.</P 4148262685Sdelphij><DIV 4149262685SdelphijCLASS="EXAMPLE" 4150262685Sdelphij><A 4151262685SdelphijNAME="BACSVARS" 4152262685Sdelphij></A 4153262685Sdelphij><P 4154262685Sdelphij><B 4155262685Sdelphij>Example 13. ACS Variables Example </B 4156262685Sdelphij></P 4157262685Sdelphij><PRE 4158262685SdelphijCLASS="PROGRAMLISTING" 4159262685Sdelphij><SPAN 4160262685SdelphijCLASS="INLINEMEDIAOBJECT" 4161262685Sdelphij>#include <ncurses.h> 4162166124Srafan 4163166124Srafanint main() 4164166124Srafan{ 4165166124Srafan initscr(); 4166166124Srafan 4167166124Srafan printw("Upper left corner "); addch(ACS_ULCORNER); printw("\n"); 4168166124Srafan printw("Lower left corner "); addch(ACS_LLCORNER); printw("\n"); 4169166124Srafan printw("Lower right corner "); addch(ACS_LRCORNER); printw("\n"); 4170166124Srafan printw("Tee pointing right "); addch(ACS_LTEE); printw("\n"); 4171166124Srafan printw("Tee pointing left "); addch(ACS_RTEE); printw("\n"); 4172166124Srafan printw("Tee pointing up "); addch(ACS_BTEE); printw("\n"); 4173166124Srafan printw("Tee pointing down "); addch(ACS_TTEE); printw("\n"); 4174166124Srafan printw("Horizontal line "); addch(ACS_HLINE); printw("\n"); 4175166124Srafan printw("Vertical line "); addch(ACS_VLINE); printw("\n"); 4176166124Srafan printw("Large Plus or cross over "); addch(ACS_PLUS); printw("\n"); 4177166124Srafan printw("Scan Line 1 "); addch(ACS_S1); printw("\n"); 4178166124Srafan printw("Scan Line 3 "); addch(ACS_S3); printw("\n"); 4179166124Srafan printw("Scan Line 7 "); addch(ACS_S7); printw("\n"); 4180166124Srafan printw("Scan Line 9 "); addch(ACS_S9); printw("\n"); 4181166124Srafan printw("Diamond "); addch(ACS_DIAMOND); printw("\n"); 4182166124Srafan printw("Checker board (stipple) "); addch(ACS_CKBOARD); printw("\n"); 4183166124Srafan printw("Degree Symbol "); addch(ACS_DEGREE); printw("\n"); 4184166124Srafan printw("Plus/Minus Symbol "); addch(ACS_PLMINUS); printw("\n"); 4185166124Srafan printw("Bullet "); addch(ACS_BULLET); printw("\n"); 4186166124Srafan printw("Arrow Pointing Left "); addch(ACS_LARROW); printw("\n"); 4187166124Srafan printw("Arrow Pointing Right "); addch(ACS_RARROW); printw("\n"); 4188166124Srafan printw("Arrow Pointing Down "); addch(ACS_DARROW); printw("\n"); 4189166124Srafan printw("Arrow Pointing Up "); addch(ACS_UARROW); printw("\n"); 4190166124Srafan printw("Board of squares "); addch(ACS_BOARD); printw("\n"); 4191166124Srafan printw("Lantern Symbol "); addch(ACS_LANTERN); printw("\n"); 4192166124Srafan printw("Solid Square Block "); addch(ACS_BLOCK); printw("\n"); 4193166124Srafan printw("Less/Equal sign "); addch(ACS_LEQUAL); printw("\n"); 4194166124Srafan printw("Greater/Equal sign "); addch(ACS_GEQUAL); printw("\n"); 4195166124Srafan printw("Pi "); addch(ACS_PI); printw("\n"); 4196166124Srafan printw("Not equal "); addch(ACS_NEQUAL); printw("\n"); 4197166124Srafan printw("UK pound sign "); addch(ACS_STERLING); printw("\n"); 4198166124Srafan 4199166124Srafan refresh(); 4200166124Srafan getch(); 4201166124Srafan endwin(); 4202166124Srafan 4203262685Sdelphij return 0; 4204262685Sdelphij}</SPAN 4205262685Sdelphij></PRE 4206262685Sdelphij></DIV 4207262685Sdelphij></DIV 4208262685Sdelphij></DIV 4209262685Sdelphij><DIV 4210262685SdelphijCLASS="SECT1" 4211262685Sdelphij><HR><H2 4212262685SdelphijCLASS="SECT1" 4213262685Sdelphij><A 4214262685SdelphijNAME="OTHERLIB" 4215262685Sdelphij>15. Other libraries</A 4216262685Sdelphij></H2 4217262685Sdelphij><P 4218262685Sdelphij>Apart from the curses library, there are few text mode libraries, which provide 4219262685Sdelphijmore functionality and a lot of features. The following sections explain three 4220262685Sdelphijstandard libraries which are usually distributed along with curses. </P 4221262685Sdelphij></DIV 4222262685Sdelphij><DIV 4223262685SdelphijCLASS="SECT1" 4224262685Sdelphij><HR><H2 4225262685SdelphijCLASS="SECT1" 4226262685Sdelphij><A 4227262685SdelphijNAME="PANELS" 4228262685Sdelphij>16. Panel Library</A 4229262685Sdelphij></H2 4230262685Sdelphij><P 4231262685Sdelphij>Now that you are proficient in curses, you wanted to do some thing big. You 4232262685Sdelphijcreated a lot of overlapping windows to give a professional windows-type look. 4233262685SdelphijUnfortunately, it soon becomes difficult to manage these. The multiple 4234262685Sdelphijrefreshes, updates plunge you into a nightmare. The overlapping windows create 4235262685Sdelphijblotches, whenever you forget to refresh the windows in the proper order. </P 4236262685Sdelphij><P 4237262685Sdelphij>Don't despair. There's an elegant solution provided in panels library. In the 4238262685Sdelphijwords of developers of ncurses </P 4239262685Sdelphij><P 4240262685Sdelphij><SPAN 4241262685SdelphijCLASS="emphasis" 4242262685Sdelphij><I 4243262685SdelphijCLASS="EMPHASIS" 4244262685Sdelphij>When your interface design is such that windows may dive deeper into the 4245262685Sdelphijvisibility stack or pop to the top at runtime, the resulting book-keeping can be 4246262685Sdelphijtedious and difficult to get right. Hence the panels library.</I 4247262685Sdelphij></SPAN 4248262685Sdelphij></P 4249262685Sdelphij><P 4250262685Sdelphij>If you have lot of overlapping windows, then panels library is the way to go. It 4251262685Sdelphijobviates the need of doing series of wnoutrefresh(), doupdate() and relieves the 4252262685Sdelphijburden of doing it correctly(bottom up). The library maintains information about 4253262685Sdelphijthe order of windows, their overlapping and update the screen properly. So why 4254262685Sdelphijwait? Let's take a close peek into panels.</P 4255262685Sdelphij><DIV 4256262685SdelphijCLASS="SECT2" 4257262685Sdelphij><HR><H3 4258262685SdelphijCLASS="SECT2" 4259262685Sdelphij><A 4260262685SdelphijNAME="PANELBASICS" 4261262685Sdelphij>16.1. The Basics</A 4262262685Sdelphij></H3 4263262685Sdelphij><P 4264262685Sdelphij>Panel object is a window that is implicitly treated as part of a deck including 4265262685Sdelphijall other panel objects. The deck is treated as a stack with the top panel being 4266262685Sdelphijcompletely visible and the other panels may or may not be obscured according to 4267262685Sdelphijtheir positions. So the basic idea is to create a stack of overlapping panels 4268262685Sdelphijand use panels library to display them correctly. There is a function similar to 4269262685Sdelphijrefresh() which, when called , displays panels in the correct order. Functions 4270262685Sdelphijare provided to hide or show panels, move panels, change its size etc.. The 4271262685Sdelphijoverlapping problem is managed by the panels library during all the calls to 4272262685Sdelphijthese functions. </P 4273262685Sdelphij><P 4274262685Sdelphij>The general flow of a panel program goes like this: 4275262685Sdelphij 4276262685Sdelphij<P 4277262685Sdelphij></P 4278262685Sdelphij><OL 4279262685SdelphijTYPE="1" 4280262685Sdelphij><LI 4281262685Sdelphij><P 4282262685Sdelphij>Create the windows (with newwin()) to be attached to the panels.</P 4283262685Sdelphij></LI 4284262685Sdelphij><LI 4285262685Sdelphij><P 4286262685Sdelphij>Create panels with the chosen visibility order. Stack them up according to the 4287262685Sdelphijdesired visibility. The function new_panel() is used to created panels.</P 4288262685Sdelphij></LI 4289262685Sdelphij><LI 4290262685Sdelphij><P 4291262685Sdelphij>Call update_panels() to write the panels to the virtual screen in correct 4292262685Sdelphijvisibility order. Do a doupdate() to show it on the screen. </P 4293262685Sdelphij></LI 4294262685Sdelphij><LI 4295262685Sdelphij><P 4296262685Sdelphij>Mainpulate the panels with show_panel(), hide_panel(), move_panel() etc. Make 4297262685Sdelphijuse of helper functions like panel_hidden() and panel_window(). Make use of user 4298262685Sdelphijpointer to store custom data for a panel. Use the functions set_panel_userptr() 4299262685Sdelphijand panel_userptr() to set and get the user pointer for a panel.</P 4300262685Sdelphij></LI 4301262685Sdelphij><LI 4302262685Sdelphij><P 4303262685Sdelphij>When you are done with the panel use del_panel() to delete the panel.</P 4304262685Sdelphij></LI 4305262685Sdelphij></OL 4306262685Sdelphij></P 4307262685Sdelphij><P 4308262685Sdelphij>Let's make the concepts clear, with some programs. The following is a simple 4309262685Sdelphijprogram which creates 3 overlapping panels and shows them on the screen. </P 4310262685Sdelphij></DIV 4311262685Sdelphij><DIV 4312262685SdelphijCLASS="SECT2" 4313262685Sdelphij><HR><H3 4314262685SdelphijCLASS="SECT2" 4315262685Sdelphij><A 4316262685SdelphijNAME="COMPILEPANELS" 4317262685Sdelphij>16.2. Compiling With the Panels Library</A 4318262685Sdelphij></H3 4319262685Sdelphij><P 4320262685Sdelphij>To use panels library functions, you have to include panel.h and to link the 4321262685Sdelphijprogram with panels library the flag -lpanel should be added along with 4322262685Sdelphij-lncurses in that order.</P 4323262685Sdelphij><PRE 4324262685SdelphijCLASS="PROGRAMLISTING" 4325262685Sdelphij> #include <panel.h> 4326166124Srafan . 4327166124Srafan . 4328166124Srafan . 4329166124Srafan 4330262685Sdelphij compile and link: gcc <program file> -lpanel -lncurses</PRE 4331262685Sdelphij><DIV 4332262685SdelphijCLASS="EXAMPLE" 4333262685Sdelphij><A 4334262685SdelphijNAME="PPASI" 4335262685Sdelphij></A 4336262685Sdelphij><P 4337262685Sdelphij><B 4338262685Sdelphij>Example 14. Panel basics</B 4339262685Sdelphij></P 4340262685Sdelphij><PRE 4341262685SdelphijCLASS="PROGRAMLISTING" 4342262685Sdelphij><SPAN 4343262685SdelphijCLASS="INLINEMEDIAOBJECT" 4344262685Sdelphij>#include <panel.h> 4345166124Srafan 4346166124Srafanint main() 4347262685Sdelphij{ WINDOW *my_wins[3]; 4348262685Sdelphij PANEL *my_panels[3]; 4349262685Sdelphij int lines = 10, cols = 40, y = 2, x = 4, i; 4350166124Srafan 4351262685Sdelphij initscr(); 4352262685Sdelphij cbreak(); 4353262685Sdelphij noecho(); 4354166124Srafan 4355262685Sdelphij /* Create windows for the panels */ 4356262685Sdelphij my_wins[0] = newwin(lines, cols, y, x); 4357262685Sdelphij my_wins[1] = newwin(lines, cols, y + 1, x + 5); 4358262685Sdelphij my_wins[2] = newwin(lines, cols, y + 2, x + 10); 4359166124Srafan 4360262685Sdelphij /* 4361262685Sdelphij * Create borders around the windows so that you can see the effect 4362262685Sdelphij * of panels 4363262685Sdelphij */ 4364262685Sdelphij for(i = 0; i < 3; ++i) 4365262685Sdelphij box(my_wins[i], 0, 0); 4366166124Srafan 4367262685Sdelphij /* Attach a panel to each window */ /* Order is bottom up */ 4368262685Sdelphij my_panels[0] = new_panel(my_wins[0]); /* Push 0, order: stdscr-0 */ 4369262685Sdelphij my_panels[1] = new_panel(my_wins[1]); /* Push 1, order: stdscr-0-1 */ 4370262685Sdelphij my_panels[2] = new_panel(my_wins[2]); /* Push 2, order: stdscr-0-1-2 */ 4371166124Srafan 4372262685Sdelphij /* Update the stacking order. 2nd panel will be on top */ 4373262685Sdelphij update_panels(); 4374166124Srafan 4375262685Sdelphij /* Show it on the screen */ 4376262685Sdelphij doupdate(); 4377262685Sdelphij 4378262685Sdelphij getch(); 4379262685Sdelphij endwin(); 4380166124Srafan} 4381262685Sdelphij</SPAN 4382262685Sdelphij></PRE 4383262685Sdelphij></DIV 4384262685Sdelphij><P 4385262685Sdelphij>As you can see, above program follows a simple flow as explained. The windows 4386262685Sdelphijare created with newwin() and then they are attached to panels with new_panel(). 4387262685SdelphijAs we attach one panel after another, the stack of panels gets updated. To put 4388262685Sdelphijthem on screen update_panels() and doupdate() are called.</P 4389262685Sdelphij></DIV 4390262685Sdelphij><DIV 4391262685SdelphijCLASS="SECT2" 4392262685Sdelphij><HR><H3 4393262685SdelphijCLASS="SECT2" 4394262685Sdelphij><A 4395262685SdelphijNAME="PANELBROWSING" 4396262685Sdelphij>16.3. Panel Window Browsing</A 4397262685Sdelphij></H3 4398262685Sdelphij><P 4399262685Sdelphij>A slightly complicated example is given below. This program creates 3 4400262685Sdelphijwindows which can be cycled through using tab. Have a look at the code.</P 4401262685Sdelphij><DIV 4402262685SdelphijCLASS="EXAMPLE" 4403262685Sdelphij><A 4404262685SdelphijNAME="PPABR" 4405262685Sdelphij></A 4406262685Sdelphij><P 4407262685Sdelphij><B 4408262685Sdelphij>Example 15. Panel Window Browsing Example </B 4409262685Sdelphij></P 4410262685Sdelphij><PRE 4411262685SdelphijCLASS="PROGRAMLISTING" 4412262685Sdelphij><SPAN 4413262685SdelphijCLASS="INLINEMEDIAOBJECT" 4414262685Sdelphij>#include <panel.h> 4415166124Srafan 4416166124Srafan#define NLINES 10 4417166124Srafan#define NCOLS 40 4418166124Srafan 4419166124Srafanvoid init_wins(WINDOW **wins, int n); 4420166124Srafanvoid win_show(WINDOW *win, char *label, int label_color); 4421166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 4422166124Srafan 4423166124Srafanint main() 4424262685Sdelphij{ WINDOW *my_wins[3]; 4425262685Sdelphij PANEL *my_panels[3]; 4426262685Sdelphij PANEL *top; 4427262685Sdelphij int ch; 4428166124Srafan 4429262685Sdelphij /* Initialize curses */ 4430262685Sdelphij initscr(); 4431262685Sdelphij start_color(); 4432262685Sdelphij cbreak(); 4433262685Sdelphij noecho(); 4434262685Sdelphij keypad(stdscr, TRUE); 4435166124Srafan 4436262685Sdelphij /* Initialize all the colors */ 4437262685Sdelphij init_pair(1, COLOR_RED, COLOR_BLACK); 4438262685Sdelphij init_pair(2, COLOR_GREEN, COLOR_BLACK); 4439262685Sdelphij init_pair(3, COLOR_BLUE, COLOR_BLACK); 4440262685Sdelphij init_pair(4, COLOR_CYAN, COLOR_BLACK); 4441166124Srafan 4442262685Sdelphij init_wins(my_wins, 3); 4443262685Sdelphij 4444262685Sdelphij /* Attach a panel to each window */ /* Order is bottom up */ 4445262685Sdelphij my_panels[0] = new_panel(my_wins[0]); /* Push 0, order: stdscr-0 */ 4446262685Sdelphij my_panels[1] = new_panel(my_wins[1]); /* Push 1, order: stdscr-0-1 */ 4447262685Sdelphij my_panels[2] = new_panel(my_wins[2]); /* Push 2, order: stdscr-0-1-2 */ 4448166124Srafan 4449262685Sdelphij /* Set up the user pointers to the next panel */ 4450262685Sdelphij set_panel_userptr(my_panels[0], my_panels[1]); 4451262685Sdelphij set_panel_userptr(my_panels[1], my_panels[2]); 4452262685Sdelphij set_panel_userptr(my_panels[2], my_panels[0]); 4453166124Srafan 4454262685Sdelphij /* Update the stacking order. 2nd panel will be on top */ 4455262685Sdelphij update_panels(); 4456166124Srafan 4457262685Sdelphij /* Show it on the screen */ 4458262685Sdelphij attron(COLOR_PAIR(4)); 4459262685Sdelphij mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)"); 4460262685Sdelphij attroff(COLOR_PAIR(4)); 4461262685Sdelphij doupdate(); 4462166124Srafan 4463262685Sdelphij top = my_panels[2]; 4464262685Sdelphij while((ch = getch()) != KEY_F(1)) 4465262685Sdelphij { switch(ch) 4466262685Sdelphij { case 9: 4467262685Sdelphij top = (PANEL *)panel_userptr(top); 4468262685Sdelphij top_panel(top); 4469262685Sdelphij break; 4470262685Sdelphij } 4471262685Sdelphij update_panels(); 4472262685Sdelphij doupdate(); 4473262685Sdelphij } 4474262685Sdelphij endwin(); 4475262685Sdelphij return 0; 4476166124Srafan} 4477166124Srafan 4478166124Srafan/* Put all the windows */ 4479166124Srafanvoid init_wins(WINDOW **wins, int n) 4480262685Sdelphij{ int x, y, i; 4481262685Sdelphij char label[80]; 4482166124Srafan 4483262685Sdelphij y = 2; 4484262685Sdelphij x = 10; 4485262685Sdelphij for(i = 0; i < n; ++i) 4486262685Sdelphij { wins[i] = newwin(NLINES, NCOLS, y, x); 4487262685Sdelphij sprintf(label, "Window Number %d", i + 1); 4488262685Sdelphij win_show(wins[i], label, i + 1); 4489262685Sdelphij y += 3; 4490262685Sdelphij x += 7; 4491262685Sdelphij } 4492166124Srafan} 4493166124Srafan 4494166124Srafan/* Show the window with a border and a label */ 4495166124Srafanvoid win_show(WINDOW *win, char *label, int label_color) 4496262685Sdelphij{ int startx, starty, height, width; 4497166124Srafan 4498262685Sdelphij getbegyx(win, starty, startx); 4499262685Sdelphij getmaxyx(win, height, width); 4500166124Srafan 4501262685Sdelphij box(win, 0, 0); 4502262685Sdelphij mvwaddch(win, 2, 0, ACS_LTEE); 4503262685Sdelphij mvwhline(win, 2, 1, ACS_HLINE, width - 2); 4504262685Sdelphij mvwaddch(win, 2, width - 1, ACS_RTEE); 4505262685Sdelphij 4506262685Sdelphij print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color)); 4507166124Srafan} 4508166124Srafan 4509166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 4510262685Sdelphij{ int length, x, y; 4511262685Sdelphij float temp; 4512166124Srafan 4513262685Sdelphij if(win == NULL) 4514262685Sdelphij win = stdscr; 4515262685Sdelphij getyx(win, y, x); 4516262685Sdelphij if(startx != 0) 4517262685Sdelphij x = startx; 4518262685Sdelphij if(starty != 0) 4519262685Sdelphij y = starty; 4520262685Sdelphij if(width == 0) 4521262685Sdelphij width = 80; 4522166124Srafan 4523262685Sdelphij length = strlen(string); 4524262685Sdelphij temp = (width - length)/ 2; 4525262685Sdelphij x = startx + (int)temp; 4526262685Sdelphij wattron(win, color); 4527262685Sdelphij mvwprintw(win, y, x, "%s", string); 4528262685Sdelphij wattroff(win, color); 4529262685Sdelphij refresh(); 4530262685Sdelphij}</SPAN 4531262685Sdelphij></PRE 4532262685Sdelphij></DIV 4533262685Sdelphij></DIV 4534262685Sdelphij><DIV 4535262685SdelphijCLASS="SECT2" 4536262685Sdelphij><HR><H3 4537262685SdelphijCLASS="SECT2" 4538262685Sdelphij><A 4539262685SdelphijNAME="USERPTRUSING" 4540262685Sdelphij>16.4. Using User Pointers</A 4541262685Sdelphij></H3 4542262685Sdelphij><P 4543262685Sdelphij>In the above example I used user pointers to find out the next window in the 4544262685Sdelphijcycle. We can attach custom information to the panel by specifying a user 4545262685Sdelphijpointer, which can point to any information you want to store. In this case I 4546262685Sdelphijstored the pointer to the next panel in the cycle. User pointer for a panel can 4547262685Sdelphijbe set with the function <TT 4548262685SdelphijCLASS="LITERAL" 4549262685Sdelphij> set_panel_userptr()</TT 4550262685Sdelphij>. 4551262685SdelphijIt can be accessed using the function <TT 4552262685SdelphijCLASS="LITERAL" 4553262685Sdelphij>panel_userptr()</TT 4554262685Sdelphij> which will return the user pointer for the panel given as 4555262685Sdelphijargument. After finding the next panel in the cycle It's brought to the top by 4556262685Sdelphijthe function top_panel(). This function brings the panel given as argument to 4557262685Sdelphijthe top of the panel stack. </P 4558262685Sdelphij></DIV 4559262685Sdelphij><DIV 4560262685SdelphijCLASS="SECT2" 4561262685Sdelphij><HR><H3 4562262685SdelphijCLASS="SECT2" 4563262685Sdelphij><A 4564262685SdelphijNAME="PANELMOVERESIZE" 4565262685Sdelphij>16.5. Moving and Resizing Panels</A 4566262685Sdelphij></H3 4567262685Sdelphij><P 4568262685Sdelphij>The function <TT 4569262685SdelphijCLASS="LITERAL" 4570262685Sdelphij>move_panel()</TT 4571262685Sdelphij> can be used to move a 4572262685Sdelphijpanel to the desired location. It does not change the position of the panel in 4573262685Sdelphijthe stack. Make sure that you use move_panel() instead mvwin() on the window 4574262685Sdelphijassociated with the panel.</P 4575262685Sdelphij><P 4576262685Sdelphij>Resizing a panel is slightly complex. There is no straight forward function 4577262685Sdelphijjust to resize the window associated with a panel. A solution to resize a panel 4578262685Sdelphijis to create a new window with the desired sizes, change the window associated 4579262685Sdelphijwith the panel using replace_panel(). Don't forget to delete the old window. The 4580262685Sdelphijwindow associated with a panel can be found by using the function 4581262685Sdelphijpanel_window().</P 4582262685Sdelphij><P 4583262685Sdelphij>The following program shows these concepts, in supposedly simple program. You 4584262685Sdelphijcan cycle through the window with <TAB> as usual. To resize or move the 4585262685Sdelphijactive panel press 'r' for resize 'm' for moving. Then use arrow keys to resize 4586262685Sdelphijor move it to the desired way and press enter to end your resizing or moving. 4587262685SdelphijThis example makes use of user data to get the required data to do the 4588262685Sdelphijoperations. </P 4589262685Sdelphij><DIV 4590262685SdelphijCLASS="EXAMPLE" 4591262685Sdelphij><A 4592262685SdelphijNAME="PPARE" 4593262685Sdelphij></A 4594262685Sdelphij><P 4595262685Sdelphij><B 4596262685Sdelphij>Example 16. Panel Moving and Resizing example </B 4597262685Sdelphij></P 4598262685Sdelphij><PRE 4599262685SdelphijCLASS="PROGRAMLISTING" 4600262685Sdelphij><SPAN 4601262685SdelphijCLASS="INLINEMEDIAOBJECT" 4602262685Sdelphij>#include <panel.h> 4603166124Srafan 4604166124Srafantypedef struct _PANEL_DATA { 4605262685Sdelphij int x, y, w, h; 4606262685Sdelphij char label[80]; 4607262685Sdelphij int label_color; 4608262685Sdelphij PANEL *next; 4609166124Srafan}PANEL_DATA; 4610166124Srafan 4611166124Srafan#define NLINES 10 4612166124Srafan#define NCOLS 40 4613166124Srafan 4614166124Srafanvoid init_wins(WINDOW **wins, int n); 4615166124Srafanvoid win_show(WINDOW *win, char *label, int label_color); 4616166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 4617166124Srafanvoid set_user_ptrs(PANEL **panels, int n); 4618166124Srafan 4619166124Srafanint main() 4620262685Sdelphij{ WINDOW *my_wins[3]; 4621262685Sdelphij PANEL *my_panels[3]; 4622262685Sdelphij PANEL_DATA *top; 4623262685Sdelphij PANEL *stack_top; 4624262685Sdelphij WINDOW *temp_win, *old_win; 4625262685Sdelphij int ch; 4626262685Sdelphij int newx, newy, neww, newh; 4627262685Sdelphij int size = FALSE, move = FALSE; 4628166124Srafan 4629262685Sdelphij /* Initialize curses */ 4630262685Sdelphij initscr(); 4631262685Sdelphij start_color(); 4632262685Sdelphij cbreak(); 4633262685Sdelphij noecho(); 4634262685Sdelphij keypad(stdscr, TRUE); 4635166124Srafan 4636262685Sdelphij /* Initialize all the colors */ 4637262685Sdelphij init_pair(1, COLOR_RED, COLOR_BLACK); 4638262685Sdelphij init_pair(2, COLOR_GREEN, COLOR_BLACK); 4639262685Sdelphij init_pair(3, COLOR_BLUE, COLOR_BLACK); 4640262685Sdelphij init_pair(4, COLOR_CYAN, COLOR_BLACK); 4641166124Srafan 4642262685Sdelphij init_wins(my_wins, 3); 4643262685Sdelphij 4644262685Sdelphij /* Attach a panel to each window */ /* Order is bottom up */ 4645262685Sdelphij my_panels[0] = new_panel(my_wins[0]); /* Push 0, order: stdscr-0 */ 4646262685Sdelphij my_panels[1] = new_panel(my_wins[1]); /* Push 1, order: stdscr-0-1 */ 4647262685Sdelphij my_panels[2] = new_panel(my_wins[2]); /* Push 2, order: stdscr-0-1-2 */ 4648166124Srafan 4649262685Sdelphij set_user_ptrs(my_panels, 3); 4650262685Sdelphij /* Update the stacking order. 2nd panel will be on top */ 4651262685Sdelphij update_panels(); 4652166124Srafan 4653262685Sdelphij /* Show it on the screen */ 4654262685Sdelphij attron(COLOR_PAIR(4)); 4655262685Sdelphij mvprintw(LINES - 3, 0, "Use 'm' for moving, 'r' for resizing"); 4656262685Sdelphij mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)"); 4657262685Sdelphij attroff(COLOR_PAIR(4)); 4658262685Sdelphij doupdate(); 4659166124Srafan 4660262685Sdelphij stack_top = my_panels[2]; 4661262685Sdelphij top = (PANEL_DATA *)panel_userptr(stack_top); 4662262685Sdelphij newx = top->x; 4663262685Sdelphij newy = top->y; 4664262685Sdelphij neww = top->w; 4665262685Sdelphij newh = top->h; 4666262685Sdelphij while((ch = getch()) != KEY_F(1)) 4667262685Sdelphij { switch(ch) 4668262685Sdelphij { case 9: /* Tab */ 4669262685Sdelphij top = (PANEL_DATA *)panel_userptr(stack_top); 4670262685Sdelphij top_panel(top->next); 4671262685Sdelphij stack_top = top->next; 4672262685Sdelphij top = (PANEL_DATA *)panel_userptr(stack_top); 4673262685Sdelphij newx = top->x; 4674262685Sdelphij newy = top->y; 4675262685Sdelphij neww = top->w; 4676262685Sdelphij newh = top->h; 4677262685Sdelphij break; 4678262685Sdelphij case 'r': /* Re-Size*/ 4679262685Sdelphij size = TRUE; 4680262685Sdelphij attron(COLOR_PAIR(4)); 4681262685Sdelphij mvprintw(LINES - 4, 0, "Entered Resizing :Use Arrow Keys to resize and press <ENTER> to end resizing"); 4682262685Sdelphij refresh(); 4683262685Sdelphij attroff(COLOR_PAIR(4)); 4684262685Sdelphij break; 4685262685Sdelphij case 'm': /* Move */ 4686262685Sdelphij attron(COLOR_PAIR(4)); 4687262685Sdelphij mvprintw(LINES - 4, 0, "Entered Moving: Use Arrow Keys to Move and press <ENTER> to end moving"); 4688262685Sdelphij refresh(); 4689262685Sdelphij attroff(COLOR_PAIR(4)); 4690262685Sdelphij move = TRUE; 4691262685Sdelphij break; 4692262685Sdelphij case KEY_LEFT: 4693262685Sdelphij if(size == TRUE) 4694262685Sdelphij { --newx; 4695262685Sdelphij ++neww; 4696262685Sdelphij } 4697262685Sdelphij if(move == TRUE) 4698262685Sdelphij --newx; 4699262685Sdelphij break; 4700262685Sdelphij case KEY_RIGHT: 4701262685Sdelphij if(size == TRUE) 4702262685Sdelphij { ++newx; 4703262685Sdelphij --neww; 4704262685Sdelphij } 4705262685Sdelphij if(move == TRUE) 4706262685Sdelphij ++newx; 4707262685Sdelphij break; 4708262685Sdelphij case KEY_UP: 4709262685Sdelphij if(size == TRUE) 4710262685Sdelphij { --newy; 4711262685Sdelphij ++newh; 4712262685Sdelphij } 4713262685Sdelphij if(move == TRUE) 4714262685Sdelphij --newy; 4715262685Sdelphij break; 4716262685Sdelphij case KEY_DOWN: 4717262685Sdelphij if(size == TRUE) 4718262685Sdelphij { ++newy; 4719262685Sdelphij --newh; 4720262685Sdelphij } 4721262685Sdelphij if(move == TRUE) 4722262685Sdelphij ++newy; 4723262685Sdelphij break; 4724262685Sdelphij case 10: /* Enter */ 4725262685Sdelphij move(LINES - 4, 0); 4726262685Sdelphij clrtoeol(); 4727262685Sdelphij refresh(); 4728262685Sdelphij if(size == TRUE) 4729262685Sdelphij { old_win = panel_window(stack_top); 4730262685Sdelphij temp_win = newwin(newh, neww, newy, newx); 4731262685Sdelphij replace_panel(stack_top, temp_win); 4732262685Sdelphij win_show(temp_win, top->label, top->label_color); 4733262685Sdelphij delwin(old_win); 4734262685Sdelphij size = FALSE; 4735262685Sdelphij } 4736262685Sdelphij if(move == TRUE) 4737262685Sdelphij { move_panel(stack_top, newy, newx); 4738262685Sdelphij move = FALSE; 4739262685Sdelphij } 4740262685Sdelphij break; 4741262685Sdelphij 4742262685Sdelphij } 4743262685Sdelphij attron(COLOR_PAIR(4)); 4744262685Sdelphij mvprintw(LINES - 3, 0, "Use 'm' for moving, 'r' for resizing"); 4745262685Sdelphij mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)"); 4746262685Sdelphij attroff(COLOR_PAIR(4)); 4747262685Sdelphij refresh(); 4748262685Sdelphij update_panels(); 4749262685Sdelphij doupdate(); 4750262685Sdelphij } 4751262685Sdelphij endwin(); 4752262685Sdelphij return 0; 4753166124Srafan} 4754166124Srafan 4755166124Srafan/* Put all the windows */ 4756166124Srafanvoid init_wins(WINDOW **wins, int n) 4757262685Sdelphij{ int x, y, i; 4758262685Sdelphij char label[80]; 4759166124Srafan 4760262685Sdelphij y = 2; 4761262685Sdelphij x = 10; 4762262685Sdelphij for(i = 0; i < n; ++i) 4763262685Sdelphij { wins[i] = newwin(NLINES, NCOLS, y, x); 4764262685Sdelphij sprintf(label, "Window Number %d", i + 1); 4765262685Sdelphij win_show(wins[i], label, i + 1); 4766262685Sdelphij y += 3; 4767262685Sdelphij x += 7; 4768262685Sdelphij } 4769166124Srafan} 4770166124Srafan 4771166124Srafan/* Set the PANEL_DATA structures for individual panels */ 4772166124Srafanvoid set_user_ptrs(PANEL **panels, int n) 4773262685Sdelphij{ PANEL_DATA *ptrs; 4774262685Sdelphij WINDOW *win; 4775262685Sdelphij int x, y, w, h, i; 4776262685Sdelphij char temp[80]; 4777262685Sdelphij 4778262685Sdelphij ptrs = (PANEL_DATA *)calloc(n, sizeof(PANEL_DATA)); 4779166124Srafan 4780262685Sdelphij for(i = 0;i < n; ++i) 4781262685Sdelphij { win = panel_window(panels[i]); 4782262685Sdelphij getbegyx(win, y, x); 4783262685Sdelphij getmaxyx(win, h, w); 4784262685Sdelphij ptrs[i].x = x; 4785262685Sdelphij ptrs[i].y = y; 4786262685Sdelphij ptrs[i].w = w; 4787262685Sdelphij ptrs[i].h = h; 4788262685Sdelphij sprintf(temp, "Window Number %d", i + 1); 4789262685Sdelphij strcpy(ptrs[i].label, temp); 4790262685Sdelphij ptrs[i].label_color = i + 1; 4791262685Sdelphij if(i + 1 == n) 4792262685Sdelphij ptrs[i].next = panels[0]; 4793262685Sdelphij else 4794262685Sdelphij ptrs[i].next = panels[i + 1]; 4795262685Sdelphij set_panel_userptr(panels[i], &ptrs[i]); 4796262685Sdelphij } 4797166124Srafan} 4798166124Srafan 4799166124Srafan/* Show the window with a border and a label */ 4800166124Srafanvoid win_show(WINDOW *win, char *label, int label_color) 4801262685Sdelphij{ int startx, starty, height, width; 4802166124Srafan 4803262685Sdelphij getbegyx(win, starty, startx); 4804262685Sdelphij getmaxyx(win, height, width); 4805166124Srafan 4806262685Sdelphij box(win, 0, 0); 4807262685Sdelphij mvwaddch(win, 2, 0, ACS_LTEE); 4808262685Sdelphij mvwhline(win, 2, 1, ACS_HLINE, width - 2); 4809262685Sdelphij mvwaddch(win, 2, width - 1, ACS_RTEE); 4810262685Sdelphij 4811262685Sdelphij print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color)); 4812166124Srafan} 4813166124Srafan 4814166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 4815262685Sdelphij{ int length, x, y; 4816262685Sdelphij float temp; 4817166124Srafan 4818262685Sdelphij if(win == NULL) 4819262685Sdelphij win = stdscr; 4820262685Sdelphij getyx(win, y, x); 4821262685Sdelphij if(startx != 0) 4822262685Sdelphij x = startx; 4823262685Sdelphij if(starty != 0) 4824262685Sdelphij y = starty; 4825262685Sdelphij if(width == 0) 4826262685Sdelphij width = 80; 4827166124Srafan 4828262685Sdelphij length = strlen(string); 4829262685Sdelphij temp = (width - length)/ 2; 4830262685Sdelphij x = startx + (int)temp; 4831262685Sdelphij wattron(win, color); 4832262685Sdelphij mvwprintw(win, y, x, "%s", string); 4833262685Sdelphij wattroff(win, color); 4834262685Sdelphij refresh(); 4835262685Sdelphij}</SPAN 4836262685Sdelphij></PRE 4837262685Sdelphij></DIV 4838262685Sdelphij><P 4839262685Sdelphij>Concentrate on the main while loop. Once it finds out the type of key pressed, 4840262685Sdelphijit takes appropriate action. If 'r' is pressed resizing mode is started. After 4841262685Sdelphijthis the new sizes are updated as the user presses the arrow keys. When the user 4842262685Sdelphijpresses <ENTER> present selection ends and panel is resized by using the 4843262685Sdelphijconcept explained. While in resizing mode the program doesn't show how the 4844262685Sdelphijwindow is getting resized. It's left as an exercise to the reader to print a 4845262685Sdelphijdotted border while it gets resized to a new position. </P 4846262685Sdelphij><P 4847262685Sdelphij>When the user presses 'm' the move mode starts. This is a bit simpler than 4848262685Sdelphijresizing. As the arrow keys are pressed the new position is updated and 4849262685Sdelphijpressing of <ENTER> causes the panel to be moved by calling the function 4850262685Sdelphijmove_panel().</P 4851262685Sdelphij><P 4852262685Sdelphij>In this program the user data which is represented as PANEL_DATA, plays very 4853262685Sdelphijimportant role in finding the associated information with a panel. As written in 4854262685Sdelphijthe comments, the PANEL_DATA stores the panel sizes, label, label color and a 4855262685Sdelphijpointer to the next panel in the cycle.</P 4856262685Sdelphij></DIV 4857262685Sdelphij><DIV 4858262685SdelphijCLASS="SECT2" 4859262685Sdelphij><HR><H3 4860262685SdelphijCLASS="SECT2" 4861262685Sdelphij><A 4862262685SdelphijNAME="PANELSHOWHIDE" 4863262685Sdelphij>16.6. Hiding and Showing Panels</A 4864262685Sdelphij></H3 4865262685Sdelphij><P 4866262685Sdelphij>A Panel can be hidden by using the function hide_panel(). This function merely 4867262685Sdelphijremoves it form the stack of panels, thus hiding it on the screen once you do 4868262685Sdelphijupdate_panels() and doupdate(). It doesn't destroy the PANEL structure 4869262685Sdelphijassociated with the hidden panel. It can be shown again by using the 4870262685Sdelphijshow_panel() function.</P 4871262685Sdelphij><P 4872262685Sdelphij>The following program shows the hiding of panels. Press 'a' or 'b' or 'c' to 4873262685Sdelphijshow or hide first, second and third windows respectively. It uses a user data 4874262685Sdelphijwith a small variable hide, which keeps track of whether the window is hidden or 4875262685Sdelphijnot. For some reason the function 4876262685Sdelphij<TT 4877262685SdelphijCLASS="LITERAL" 4878262685Sdelphij>panel_hidden()</TT 4879262685Sdelphij> which tells whether a panel is 4880262685Sdelphijhidden or not is not working. A bug report was also presented by Michael Andres 4881262685Sdelphij<A 4882262685SdelphijHREF="http://www.geocrawler.com/archives/3/344/1999/9/0/2643549/" 4883262685SdelphijTARGET="_top" 4884262685Sdelphij> here</A 4885262685Sdelphij></P 4886262685Sdelphij><DIV 4887262685SdelphijCLASS="EXAMPLE" 4888262685Sdelphij><A 4889262685SdelphijNAME="PPAHI" 4890262685Sdelphij></A 4891262685Sdelphij><P 4892262685Sdelphij><B 4893262685Sdelphij>Example 17. Panel Hiding and Showing example </B 4894262685Sdelphij></P 4895262685Sdelphij><PRE 4896262685SdelphijCLASS="PROGRAMLISTING" 4897262685Sdelphij><SPAN 4898262685SdelphijCLASS="INLINEMEDIAOBJECT" 4899262685Sdelphij>#include <panel.h> 4900166124Srafan 4901166124Srafantypedef struct _PANEL_DATA { 4902262685Sdelphij int hide; /* TRUE if panel is hidden */ 4903166124Srafan}PANEL_DATA; 4904166124Srafan 4905166124Srafan#define NLINES 10 4906166124Srafan#define NCOLS 40 4907166124Srafan 4908166124Srafanvoid init_wins(WINDOW **wins, int n); 4909166124Srafanvoid win_show(WINDOW *win, char *label, int label_color); 4910166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 4911166124Srafan 4912166124Srafanint main() 4913262685Sdelphij{ WINDOW *my_wins[3]; 4914262685Sdelphij PANEL *my_panels[3]; 4915262685Sdelphij PANEL_DATA panel_datas[3]; 4916262685Sdelphij PANEL_DATA *temp; 4917262685Sdelphij int ch; 4918166124Srafan 4919262685Sdelphij /* Initialize curses */ 4920262685Sdelphij initscr(); 4921262685Sdelphij start_color(); 4922262685Sdelphij cbreak(); 4923262685Sdelphij noecho(); 4924262685Sdelphij keypad(stdscr, TRUE); 4925166124Srafan 4926262685Sdelphij /* Initialize all the colors */ 4927262685Sdelphij init_pair(1, COLOR_RED, COLOR_BLACK); 4928262685Sdelphij init_pair(2, COLOR_GREEN, COLOR_BLACK); 4929262685Sdelphij init_pair(3, COLOR_BLUE, COLOR_BLACK); 4930262685Sdelphij init_pair(4, COLOR_CYAN, COLOR_BLACK); 4931166124Srafan 4932262685Sdelphij init_wins(my_wins, 3); 4933262685Sdelphij 4934262685Sdelphij /* Attach a panel to each window */ /* Order is bottom up */ 4935262685Sdelphij my_panels[0] = new_panel(my_wins[0]); /* Push 0, order: stdscr-0 */ 4936262685Sdelphij my_panels[1] = new_panel(my_wins[1]); /* Push 1, order: stdscr-0-1 */ 4937262685Sdelphij my_panels[2] = new_panel(my_wins[2]); /* Push 2, order: stdscr-0-1-2 */ 4938166124Srafan 4939262685Sdelphij /* Initialize panel datas saying that nothing is hidden */ 4940262685Sdelphij panel_datas[0].hide = FALSE; 4941262685Sdelphij panel_datas[1].hide = FALSE; 4942262685Sdelphij panel_datas[2].hide = FALSE; 4943166124Srafan 4944262685Sdelphij set_panel_userptr(my_panels[0], &panel_datas[0]); 4945262685Sdelphij set_panel_userptr(my_panels[1], &panel_datas[1]); 4946262685Sdelphij set_panel_userptr(my_panels[2], &panel_datas[2]); 4947166124Srafan 4948262685Sdelphij /* Update the stacking order. 2nd panel will be on top */ 4949262685Sdelphij update_panels(); 4950166124Srafan 4951262685Sdelphij /* Show it on the screen */ 4952262685Sdelphij attron(COLOR_PAIR(4)); 4953262685Sdelphij mvprintw(LINES - 3, 0, "Show or Hide a window with 'a'(first window) 'b'(Second Window) 'c'(Third Window)"); 4954262685Sdelphij mvprintw(LINES - 2, 0, "F1 to Exit"); 4955166124Srafan 4956262685Sdelphij attroff(COLOR_PAIR(4)); 4957262685Sdelphij doupdate(); 4958262685Sdelphij 4959262685Sdelphij while((ch = getch()) != KEY_F(1)) 4960262685Sdelphij { switch(ch) 4961262685Sdelphij { case 'a': 4962262685Sdelphij temp = (PANEL_DATA *)panel_userptr(my_panels[0]); 4963262685Sdelphij if(temp->hide == FALSE) 4964262685Sdelphij { hide_panel(my_panels[0]); 4965262685Sdelphij temp->hide = TRUE; 4966262685Sdelphij } 4967262685Sdelphij else 4968262685Sdelphij { show_panel(my_panels[0]); 4969262685Sdelphij temp->hide = FALSE; 4970262685Sdelphij } 4971262685Sdelphij break; 4972262685Sdelphij case 'b': 4973262685Sdelphij temp = (PANEL_DATA *)panel_userptr(my_panels[1]); 4974262685Sdelphij if(temp->hide == FALSE) 4975262685Sdelphij { hide_panel(my_panels[1]); 4976262685Sdelphij temp->hide = TRUE; 4977262685Sdelphij } 4978262685Sdelphij else 4979262685Sdelphij { show_panel(my_panels[1]); 4980262685Sdelphij temp->hide = FALSE; 4981262685Sdelphij } 4982262685Sdelphij break; 4983262685Sdelphij case 'c': 4984262685Sdelphij temp = (PANEL_DATA *)panel_userptr(my_panels[2]); 4985262685Sdelphij if(temp->hide == FALSE) 4986262685Sdelphij { hide_panel(my_panels[2]); 4987262685Sdelphij temp->hide = TRUE; 4988262685Sdelphij } 4989262685Sdelphij else 4990262685Sdelphij { show_panel(my_panels[2]); 4991262685Sdelphij temp->hide = FALSE; 4992262685Sdelphij } 4993262685Sdelphij break; 4994262685Sdelphij } 4995262685Sdelphij update_panels(); 4996262685Sdelphij doupdate(); 4997262685Sdelphij } 4998262685Sdelphij endwin(); 4999262685Sdelphij return 0; 5000166124Srafan} 5001166124Srafan 5002166124Srafan/* Put all the windows */ 5003166124Srafanvoid init_wins(WINDOW **wins, int n) 5004262685Sdelphij{ int x, y, i; 5005262685Sdelphij char label[80]; 5006166124Srafan 5007262685Sdelphij y = 2; 5008262685Sdelphij x = 10; 5009262685Sdelphij for(i = 0; i < n; ++i) 5010262685Sdelphij { wins[i] = newwin(NLINES, NCOLS, y, x); 5011262685Sdelphij sprintf(label, "Window Number %d", i + 1); 5012262685Sdelphij win_show(wins[i], label, i + 1); 5013262685Sdelphij y += 3; 5014262685Sdelphij x += 7; 5015262685Sdelphij } 5016166124Srafan} 5017166124Srafan 5018166124Srafan/* Show the window with a border and a label */ 5019166124Srafanvoid win_show(WINDOW *win, char *label, int label_color) 5020262685Sdelphij{ int startx, starty, height, width; 5021166124Srafan 5022262685Sdelphij getbegyx(win, starty, startx); 5023262685Sdelphij getmaxyx(win, height, width); 5024166124Srafan 5025262685Sdelphij box(win, 0, 0); 5026262685Sdelphij mvwaddch(win, 2, 0, ACS_LTEE); 5027262685Sdelphij mvwhline(win, 2, 1, ACS_HLINE, width - 2); 5028262685Sdelphij mvwaddch(win, 2, width - 1, ACS_RTEE); 5029262685Sdelphij 5030262685Sdelphij print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color)); 5031166124Srafan} 5032166124Srafan 5033166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 5034262685Sdelphij{ int length, x, y; 5035262685Sdelphij float temp; 5036166124Srafan 5037262685Sdelphij if(win == NULL) 5038262685Sdelphij win = stdscr; 5039262685Sdelphij getyx(win, y, x); 5040262685Sdelphij if(startx != 0) 5041262685Sdelphij x = startx; 5042262685Sdelphij if(starty != 0) 5043262685Sdelphij y = starty; 5044262685Sdelphij if(width == 0) 5045262685Sdelphij width = 80; 5046166124Srafan 5047262685Sdelphij length = strlen(string); 5048262685Sdelphij temp = (width - length)/ 2; 5049262685Sdelphij x = startx + (int)temp; 5050262685Sdelphij wattron(win, color); 5051262685Sdelphij mvwprintw(win, y, x, "%s", string); 5052262685Sdelphij wattroff(win, color); 5053262685Sdelphij refresh(); 5054262685Sdelphij}</SPAN 5055262685Sdelphij></PRE 5056262685Sdelphij></DIV 5057262685Sdelphij></DIV 5058262685Sdelphij><DIV 5059262685SdelphijCLASS="SECT2" 5060262685Sdelphij><HR><H3 5061262685SdelphijCLASS="SECT2" 5062262685Sdelphij><A 5063262685SdelphijNAME="PANELABOVE" 5064262685Sdelphij>16.7. panel_above() and panel_below() Functions</A 5065262685Sdelphij></H3 5066262685Sdelphij><P 5067262685Sdelphij>The functions <TT 5068262685SdelphijCLASS="LITERAL" 5069262685Sdelphij>panel_above()</TT 5070262685Sdelphij> and 5071262685Sdelphij<TT 5072262685SdelphijCLASS="LITERAL" 5073262685Sdelphij>panel_below()</TT 5074262685Sdelphij> can be used to find out the panel 5075262685Sdelphijabove and below a panel. If the argument to these functions is NULL, then they 5076262685Sdelphijreturn a pointer to bottom panel and top panel respectively.</P 5077262685Sdelphij></DIV 5078262685Sdelphij></DIV 5079262685Sdelphij><DIV 5080262685SdelphijCLASS="SECT1" 5081262685Sdelphij><HR><H2 5082262685SdelphijCLASS="SECT1" 5083262685Sdelphij><A 5084262685SdelphijNAME="MENUS" 5085262685Sdelphij>17. Menus Library</A 5086262685Sdelphij></H2 5087262685Sdelphij><P 5088262685Sdelphij>The menus library provides a nice extension to basic curses, through which you 5089262685Sdelphijcan create menus. It provides a set of functions to create menus. But they have 5090262685Sdelphijto be customized to give a nicer look, with colors etc. Let's get into the 5091262685Sdelphijdetails.</P 5092262685Sdelphij><P 5093262685Sdelphij>A menu is a screen display that assists the user to choose some subset of a 5094262685Sdelphijgiven set of items. To put it simple, a menu is a collection of items from which 5095262685Sdelphijone or more items can be chosen. Some readers might not be aware of multiple 5096262685Sdelphijitem selection capability. Menu library provides functionality to write menus 5097262685Sdelphijfrom which the user can chose more than one item as the preferred choice. This 5098262685Sdelphijis dealt with in a later section. Now it is time for some rudiments.</P 5099262685Sdelphij><DIV 5100262685SdelphijCLASS="SECT2" 5101262685Sdelphij><HR><H3 5102262685SdelphijCLASS="SECT2" 5103262685Sdelphij><A 5104262685SdelphijNAME="MENUBASICS" 5105262685Sdelphij>17.1. The Basics</A 5106262685Sdelphij></H3 5107262685Sdelphij><P 5108262685Sdelphij>To create menus, you first create items, and then post the menu to the display. 5109262685SdelphijAfter that, all the processing of user responses is done in an elegant function 5110262685Sdelphijmenu_driver() which is the work horse of any menu program. </P 5111262685Sdelphij><P 5112262685Sdelphij>The general flow of control of a menu program looks like this. 5113262685Sdelphij<P 5114262685Sdelphij></P 5115262685Sdelphij><OL 5116262685SdelphijTYPE="1" 5117262685Sdelphij><LI 5118262685Sdelphij><P 5119262685Sdelphij>Initialize curses</P 5120262685Sdelphij></LI 5121262685Sdelphij><LI 5122262685Sdelphij><P 5123262685Sdelphij>Create items using new_item(). You can specify a name and description for the 5124262685Sdelphijitems.</P 5125262685Sdelphij></LI 5126262685Sdelphij><LI 5127262685Sdelphij><P 5128262685Sdelphij>Create the menu with new_menu() by specifying the items to be attached with.</P 5129262685Sdelphij></LI 5130262685Sdelphij><LI 5131262685Sdelphij><P 5132262685Sdelphij>Post the menu with menu_post() and refresh the screen.</P 5133262685Sdelphij></LI 5134262685Sdelphij><LI 5135262685Sdelphij><P 5136262685Sdelphij>Process the user requests with a loop and do necessary updates to menu with 5137262685Sdelphijmenu_driver.</P 5138262685Sdelphij></LI 5139262685Sdelphij><LI 5140262685Sdelphij><P 5141262685Sdelphij>Unpost the menu with menu_unpost()</P 5142262685Sdelphij></LI 5143262685Sdelphij><LI 5144262685Sdelphij><P 5145262685Sdelphij>Free the memory allocated to menu by free_menu()</P 5146262685Sdelphij></LI 5147262685Sdelphij><LI 5148262685Sdelphij><P 5149262685Sdelphij>Free the memory allocated to the items with free_item() </P 5150262685Sdelphij></LI 5151262685Sdelphij><LI 5152262685Sdelphij><P 5153262685Sdelphij>End curses </P 5154262685Sdelphij></LI 5155262685Sdelphij></OL 5156262685Sdelphij></P 5157262685Sdelphij><P 5158262685Sdelphij>Let's see a program which prints a simple menu and updates the current selection 5159262685Sdelphijwith up, down arrows. </P 5160262685Sdelphij></DIV 5161262685Sdelphij><DIV 5162262685SdelphijCLASS="SECT2" 5163262685Sdelphij><HR><H3 5164262685SdelphijCLASS="SECT2" 5165262685Sdelphij><A 5166262685SdelphijNAME="COMPILEMENUS" 5167262685Sdelphij>17.2. Compiling With the Menu Library</A 5168262685Sdelphij></H3 5169262685Sdelphij><P 5170262685Sdelphij>To use menu library functions, you have to include menu.h and to link the 5171262685Sdelphijprogram with menu library the flag -lmenu should be added along with -lncurses 5172262685Sdelphijin that order.</P 5173262685Sdelphij><PRE 5174262685SdelphijCLASS="PROGRAMLISTING" 5175262685Sdelphij> #include <menu.h> 5176166124Srafan . 5177166124Srafan . 5178166124Srafan . 5179166124Srafan 5180262685Sdelphij compile and link: gcc <program file> -lmenu -lncurses</PRE 5181262685Sdelphij><DIV 5182262685SdelphijCLASS="EXAMPLE" 5183262685Sdelphij><A 5184262685SdelphijNAME="MMESI" 5185262685Sdelphij></A 5186262685Sdelphij><P 5187262685Sdelphij><B 5188262685Sdelphij>Example 18. Menu Basics </B 5189262685Sdelphij></P 5190262685Sdelphij><PRE 5191262685SdelphijCLASS="PROGRAMLISTING" 5192262685Sdelphij><SPAN 5193262685SdelphijCLASS="INLINEMEDIAOBJECT" 5194262685Sdelphij>#include <curses.h> 5195262685Sdelphij#include <menu.h> 5196166124Srafan 5197166124Srafan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 5198262685Sdelphij#define CTRLD 4 5199166124Srafan 5200166124Srafanchar *choices[] = { 5201166124Srafan "Choice 1", 5202166124Srafan "Choice 2", 5203166124Srafan "Choice 3", 5204166124Srafan "Choice 4", 5205166124Srafan "Exit", 5206166124Srafan }; 5207166124Srafan 5208166124Srafanint main() 5209262685Sdelphij{ ITEM **my_items; 5210262685Sdelphij int c; 5211262685Sdelphij MENU *my_menu; 5212262685Sdelphij int n_choices, i; 5213262685Sdelphij ITEM *cur_item; 5214262685Sdelphij 5215262685Sdelphij 5216262685Sdelphij initscr(); 5217262685Sdelphij cbreak(); 5218262685Sdelphij noecho(); 5219262685Sdelphij keypad(stdscr, TRUE); 5220262685Sdelphij 5221262685Sdelphij n_choices = ARRAY_SIZE(choices); 5222262685Sdelphij my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *)); 5223166124Srafan 5224262685Sdelphij for(i = 0; i < n_choices; ++i) 5225262685Sdelphij my_items[i] = new_item(choices[i], choices[i]); 5226262685Sdelphij my_items[n_choices] = (ITEM *)NULL; 5227166124Srafan 5228262685Sdelphij my_menu = new_menu((ITEM **)my_items); 5229262685Sdelphij mvprintw(LINES - 2, 0, "F1 to Exit"); 5230262685Sdelphij post_menu(my_menu); 5231262685Sdelphij refresh(); 5232166124Srafan 5233262685Sdelphij while((c = getch()) != KEY_F(1)) 5234262685Sdelphij { switch(c) 5235262685Sdelphij { case KEY_DOWN: 5236262685Sdelphij menu_driver(my_menu, REQ_DOWN_ITEM); 5237262685Sdelphij break; 5238262685Sdelphij case KEY_UP: 5239262685Sdelphij menu_driver(my_menu, REQ_UP_ITEM); 5240262685Sdelphij break; 5241262685Sdelphij } 5242262685Sdelphij } 5243166124Srafan 5244262685Sdelphij free_item(my_items[0]); 5245262685Sdelphij free_item(my_items[1]); 5246262685Sdelphij free_menu(my_menu); 5247262685Sdelphij endwin(); 5248166124Srafan} 5249262685Sdelphij </SPAN 5250262685Sdelphij></PRE 5251262685Sdelphij></DIV 5252262685Sdelphij><P 5253262685Sdelphij>This program demonstrates the basic concepts involved in creating a menu using 5254262685Sdelphijmenus library. First we create the items using new_item() and then attach them 5255262685Sdelphijto the menu with new_menu() function. After posting the menu and refreshing the 5256262685Sdelphijscreen, the main processing loop starts. It reads user input and takes 5257262685Sdelphijcorresponding action. The function menu_driver() is the main work horse of the 5258262685Sdelphijmenu system. The second parameter to this function tells what's to be done with 5259262685Sdelphijthe menu. According to the parameter, menu_driver() does the corresponding task. 5260262685SdelphijThe value can be either a menu navigational request, an ascii character, or a 5261262685SdelphijKEY_MOUSE special key associated with a mouse event.</P 5262262685Sdelphij><P 5263262685Sdelphij>The menu_driver accepts following navigational requests. 5264262685Sdelphij<PRE 5265262685SdelphijCLASS="PROGRAMLISTING" 5266262685Sdelphij> REQ_LEFT_ITEM Move left to an item. 5267166124Srafan REQ_RIGHT_ITEM Move right to an item. 5268166124Srafan REQ_UP_ITEM Move up to an item. 5269166124Srafan REQ_DOWN_ITEM Move down to an item. 5270166124Srafan REQ_SCR_ULINE Scroll up a line. 5271166124Srafan REQ_SCR_DLINE Scroll down a line. 5272166124Srafan REQ_SCR_DPAGE Scroll down a page. 5273166124Srafan REQ_SCR_UPAGE Scroll up a page. 5274166124Srafan REQ_FIRST_ITEM Move to the first item. 5275166124Srafan REQ_LAST_ITEM Move to the last item. 5276166124Srafan REQ_NEXT_ITEM Move to the next item. 5277166124Srafan REQ_PREV_ITEM Move to the previous item. 5278166124Srafan REQ_TOGGLE_ITEM Select/deselect an item. 5279166124Srafan REQ_CLEAR_PATTERN Clear the menu pattern buffer. 5280166124Srafan REQ_BACK_PATTERN Delete the previous character from the pattern buffer. 5281166124Srafan REQ_NEXT_MATCH Move to the next item matching the pattern match. 5282262685Sdelphij REQ_PREV_MATCH Move to the previous item matching the pattern match. </PRE 5283262685Sdelphij></P 5284262685Sdelphij><P 5285262685Sdelphij>Don't get overwhelmed by the number of options. We will see them slowly one 5286262685Sdelphijafter another. The options of interest in this example are REQ_UP_ITEM and 5287262685SdelphijREQ_DOWN_ITEM. These two options when passed to menu_driver, menu driver 5288262685Sdelphijupdates the current item to one item up or down respectively.</P 5289262685Sdelphij></DIV 5290262685Sdelphij><DIV 5291262685SdelphijCLASS="SECT2" 5292262685Sdelphij><HR><H3 5293262685SdelphijCLASS="SECT2" 5294262685Sdelphij><A 5295262685SdelphijNAME="MENUDRIVER" 5296262685Sdelphij>17.3. Menu Driver: The work horse of the menu system</A 5297262685Sdelphij></H3 5298262685Sdelphij><P 5299262685Sdelphij>As you have seen in the above example, menu_driver plays an important role in 5300262685Sdelphijupdating the menu. It is very important to understand various options it takes 5301262685Sdelphijand what they do. As explained above, the second parameter to menu_driver() can 5302262685Sdelphijbe either a navigational request, a printable character or a KEY_MOUSE key. 5303262685SdelphijLet's dissect the different navigational requests.</P 5304262685Sdelphij><P 5305262685Sdelphij></P 5306262685Sdelphij><UL 5307262685Sdelphij><LI 5308262685Sdelphij><P 5309262685Sdelphij><SPAN 5310262685SdelphijCLASS="emphasis" 5311262685Sdelphij><I 5312262685SdelphijCLASS="EMPHASIS" 5313262685Sdelphij>REQ_LEFT_ITEM and REQ_RIGHT_ITEM</I 5314262685Sdelphij></SPAN 5315262685Sdelphij></P 5316262685Sdelphij><P 5317262685Sdelphij>A Menu can be displayed with multiple columns for more than one item. This can 5318262685Sdelphijbe done by using the <TT 5319262685SdelphijCLASS="LITERAL" 5320262685Sdelphij>menu_format()</TT 5321262685Sdelphij>function. 5322262685SdelphijWhen a multi columnar menu is displayed these requests cause the menu driver to 5323262685Sdelphijmove the current selection to left or right.</P 5324262685Sdelphij></LI 5325262685Sdelphij><LI 5326262685Sdelphij><P 5327262685Sdelphij><SPAN 5328262685SdelphijCLASS="emphasis" 5329262685Sdelphij><I 5330262685SdelphijCLASS="EMPHASIS" 5331262685Sdelphij>REQ_UP_ITEM and REQ_DOWN_ITEM </I 5332262685Sdelphij></SPAN 5333262685Sdelphij> </P 5334262685Sdelphij><P 5335262685Sdelphij>These two options you have seen in the above example. These options when given, 5336262685Sdelphijmakes the menu_driver to move the current selection to an item up or down.</P 5337262685Sdelphij></LI 5338262685Sdelphij><LI 5339262685Sdelphij><P 5340262685Sdelphij> <SPAN 5341262685SdelphijCLASS="emphasis" 5342262685Sdelphij><I 5343262685SdelphijCLASS="EMPHASIS" 5344262685Sdelphij>REQ_SCR_* options</I 5345262685Sdelphij></SPAN 5346262685Sdelphij> </P 5347262685Sdelphij><P 5348262685Sdelphij>The four options REQ_SCR_ULINE, REQ_SCR_DLINE, REQ_SCR_DPAGE, REQ_SCR_UPAGE are 5349262685Sdelphijrelated to scrolling. If all the items in the menu cannot be displayed in the 5350262685Sdelphijmenu sub window, then the menu is scrollable. These requests can be given to the 5351262685Sdelphijmenu_driver to do the scrolling either one line up, down or one page down or up 5352262685Sdelphijrespectively. </P 5353262685Sdelphij></LI 5354262685Sdelphij><LI 5355262685Sdelphij><P 5356262685Sdelphij><SPAN 5357262685SdelphijCLASS="emphasis" 5358262685Sdelphij><I 5359262685SdelphijCLASS="EMPHASIS" 5360262685Sdelphij>REQ_FIRST_ITEM, REQ_LAST_ITEM, REQ_NEXT_ITEM and 5361262685SdelphijREQ_PREV_ITEM </I 5362262685Sdelphij></SPAN 5363262685Sdelphij> </P 5364262685Sdelphij><P 5365262685Sdelphij>These requests are self explanatory.</P 5366262685Sdelphij></LI 5367262685Sdelphij><LI 5368262685Sdelphij><P 5369262685Sdelphij> <SPAN 5370262685SdelphijCLASS="emphasis" 5371262685Sdelphij><I 5372262685SdelphijCLASS="EMPHASIS" 5373262685Sdelphij>REQ_TOGGLE_ITEM</I 5374262685Sdelphij></SPAN 5375262685Sdelphij> </P 5376262685Sdelphij><P 5377262685Sdelphij>This request when given, toggles the present selection. This option is to be 5378262685Sdelphijused only in a multi valued menu. So to use this request the option O_ONEVALUE 5379262685Sdelphijmust be off. This option can be made off or on with set_menu_opts().</P 5380262685Sdelphij></LI 5381262685Sdelphij><LI 5382262685Sdelphij><P 5383262685Sdelphij> <SPAN 5384262685SdelphijCLASS="emphasis" 5385262685Sdelphij><I 5386262685SdelphijCLASS="EMPHASIS" 5387262685Sdelphij>Pattern Requests </I 5388262685Sdelphij></SPAN 5389262685Sdelphij></P 5390262685Sdelphij><P 5391262685Sdelphij>Every menu has an associated pattern buffer, which is used to find the nearest 5392262685Sdelphijmatch to the ascii characters entered by the user. Whenever ascii characters are 5393262685Sdelphijgiven to menu_driver, it puts in to the pattern buffer. It also tries to find 5394262685Sdelphijthe nearest match to the pattern in the items list and moves current selection 5395262685Sdelphijto that item. The request REQ_CLEAR_PATTERN clears the pattern buffer. The 5396262685Sdelphijrequest REQ_BACK_PATTERN deletes the previous character in the pattern buffer. 5397262685SdelphijIn case the pattern matches more than one item then the matched items can be 5398262685Sdelphijcycled through REQ_NEXT_MATCH and REQ_PREV_MATCH which move the current 5399262685Sdelphijselection to the next and previous matches respectively.</P 5400262685Sdelphij></LI 5401262685Sdelphij><LI 5402262685Sdelphij><P 5403262685Sdelphij> <SPAN 5404262685SdelphijCLASS="emphasis" 5405262685Sdelphij><I 5406262685SdelphijCLASS="EMPHASIS" 5407262685Sdelphij>Mouse Requests</I 5408262685Sdelphij></SPAN 5409262685Sdelphij></P 5410262685Sdelphij><P 5411262685Sdelphij>In case of KEY_MOUSE requests, according to the mouse position an action is 5412262685Sdelphijtaken accordingly. The action to be taken is explained in the man page as, </P 5413262685Sdelphij><PRE 5414262685SdelphijCLASS="PROGRAMLISTING" 5415262685Sdelphij><SPAN 5416262685SdelphijCLASS="emphasis" 5417262685Sdelphij><I 5418262685SdelphijCLASS="EMPHASIS" 5419262685Sdelphij> If the second argument is the KEY_MOUSE special key, the 5420166124Srafan associated mouse event is translated into one of the above 5421166124Srafan pre-defined requests. Currently only clicks in the user 5422166124Srafan window (e.g. inside the menu display area or the decora­ 5423166124Srafan tion window) are handled. If you click above the display 5424166124Srafan region of the menu, a REQ_SCR_ULINE is generated, if you 5425166124Srafan doubleclick a REQ_SCR_UPAGE is generated and if you 5426166124Srafan tripleclick a REQ_FIRST_ITEM is generated. If you click 5427166124Srafan below the display region of the menu, a REQ_SCR_DLINE is 5428166124Srafan generated, if you doubleclick a REQ_SCR_DPAGE is generated 5429166124Srafan and if you tripleclick a REQ_LAST_ITEM is generated. If 5430166124Srafan you click at an item inside the display area of the menu, 5431262685Sdelphij the menu cursor is positioned to that item.</I 5432262685Sdelphij></SPAN 5433262685Sdelphij></PRE 5434262685Sdelphij></LI 5435262685Sdelphij></UL 5436262685Sdelphij><P 5437262685Sdelphij>Each of the above requests will be explained in the following lines with several 5438262685Sdelphijexamples whenever appropriate.</P 5439262685Sdelphij></DIV 5440262685Sdelphij><DIV 5441262685SdelphijCLASS="SECT2" 5442262685Sdelphij><HR><H3 5443262685SdelphijCLASS="SECT2" 5444262685Sdelphij><A 5445262685SdelphijNAME="MENUWINDOWS" 5446262685Sdelphij>17.4. Menu Windows</A 5447262685Sdelphij></H3 5448262685Sdelphij><P 5449262685Sdelphij>Every menu created is associated with a window and a sub window. The menu window 5450262685Sdelphijdisplays any title or border associated with the menu. The menu sub window 5451262685Sdelphijdisplays the menu items currently available for selection. But we didn't specify 5452262685Sdelphijany window or sub window in the simple example. When a window is not specified, 5453262685Sdelphijstdscr is taken as the main window, and then menu system calculates the sub 5454262685Sdelphijwindow size required for the display of items. Then items are displayed in the 5455262685Sdelphijcalculated sub window. So let's play with these windows and display a menu with 5456262685Sdelphija border and a title.</P 5457262685Sdelphij><DIV 5458262685SdelphijCLASS="EXAMPLE" 5459262685Sdelphij><A 5460262685SdelphijNAME="MMEWI" 5461262685Sdelphij></A 5462262685Sdelphij><P 5463262685Sdelphij><B 5464262685Sdelphij>Example 19. Menu Windows Usage example </B 5465262685Sdelphij></P 5466262685Sdelphij><PRE 5467262685SdelphijCLASS="PROGRAMLISTING" 5468262685Sdelphij><SPAN 5469262685SdelphijCLASS="INLINEMEDIAOBJECT" 5470262685Sdelphij>#include <menu.h> 5471166124Srafan 5472166124Srafan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 5473262685Sdelphij#define CTRLD 4 5474166124Srafan 5475166124Srafanchar *choices[] = { 5476166124Srafan "Choice 1", 5477166124Srafan "Choice 2", 5478166124Srafan "Choice 3", 5479166124Srafan "Choice 4", 5480166124Srafan "Exit", 5481166124Srafan (char *)NULL, 5482166124Srafan }; 5483166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 5484166124Srafan 5485166124Srafanint main() 5486262685Sdelphij{ ITEM **my_items; 5487262685Sdelphij int c; 5488262685Sdelphij MENU *my_menu; 5489166124Srafan WINDOW *my_menu_win; 5490166124Srafan int n_choices, i; 5491262685Sdelphij 5492262685Sdelphij /* Initialize curses */ 5493262685Sdelphij initscr(); 5494262685Sdelphij start_color(); 5495166124Srafan cbreak(); 5496166124Srafan noecho(); 5497262685Sdelphij keypad(stdscr, TRUE); 5498262685Sdelphij init_pair(1, COLOR_RED, COLOR_BLACK); 5499166124Srafan 5500262685Sdelphij /* Create items */ 5501166124Srafan n_choices = ARRAY_SIZE(choices); 5502166124Srafan my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *)); 5503262685Sdelphij for(i = 0; i < n_choices; ++i) 5504166124Srafan my_items[i] = new_item(choices[i], choices[i]); 5505166124Srafan 5506262685Sdelphij /* Crate menu */ 5507262685Sdelphij my_menu = new_menu((ITEM **)my_items); 5508166124Srafan 5509262685Sdelphij /* Create the window to be associated with the menu */ 5510166124Srafan my_menu_win = newwin(10, 40, 4, 4); 5511166124Srafan keypad(my_menu_win, TRUE); 5512166124Srafan 5513262685Sdelphij /* Set main window and sub window */ 5514166124Srafan set_menu_win(my_menu, my_menu_win); 5515166124Srafan set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1)); 5516166124Srafan 5517262685Sdelphij /* Set menu mark to the string " * " */ 5518166124Srafan set_menu_mark(my_menu, " * "); 5519166124Srafan 5520262685Sdelphij /* Print a border around the main window and print a title */ 5521166124Srafan box(my_menu_win, 0, 0); 5522262685Sdelphij print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1)); 5523262685Sdelphij mvwaddch(my_menu_win, 2, 0, ACS_LTEE); 5524262685Sdelphij mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38); 5525262685Sdelphij mvwaddch(my_menu_win, 2, 39, ACS_RTEE); 5526262685Sdelphij mvprintw(LINES - 2, 0, "F1 to exit"); 5527262685Sdelphij refresh(); 5528166124Srafan 5529262685Sdelphij /* Post the menu */ 5530262685Sdelphij post_menu(my_menu); 5531262685Sdelphij wrefresh(my_menu_win); 5532166124Srafan 5533262685Sdelphij while((c = wgetch(my_menu_win)) != KEY_F(1)) 5534262685Sdelphij { switch(c) 5535262685Sdelphij { case KEY_DOWN: 5536262685Sdelphij menu_driver(my_menu, REQ_DOWN_ITEM); 5537262685Sdelphij break; 5538262685Sdelphij case KEY_UP: 5539262685Sdelphij menu_driver(my_menu, REQ_UP_ITEM); 5540262685Sdelphij break; 5541262685Sdelphij } 5542166124Srafan wrefresh(my_menu_win); 5543262685Sdelphij } 5544166124Srafan 5545262685Sdelphij /* Unpost and free all the memory taken up */ 5546166124Srafan unpost_menu(my_menu); 5547166124Srafan free_menu(my_menu); 5548262685Sdelphij for(i = 0; i < n_choices; ++i) 5549166124Srafan free_item(my_items[i]); 5550262685Sdelphij endwin(); 5551166124Srafan} 5552166124Srafan 5553166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 5554262685Sdelphij{ int length, x, y; 5555262685Sdelphij float temp; 5556166124Srafan 5557262685Sdelphij if(win == NULL) 5558262685Sdelphij win = stdscr; 5559262685Sdelphij getyx(win, y, x); 5560262685Sdelphij if(startx != 0) 5561262685Sdelphij x = startx; 5562262685Sdelphij if(starty != 0) 5563262685Sdelphij y = starty; 5564262685Sdelphij if(width == 0) 5565262685Sdelphij width = 80; 5566166124Srafan 5567262685Sdelphij length = strlen(string); 5568262685Sdelphij temp = (width - length)/ 2; 5569262685Sdelphij x = startx + (int)temp; 5570262685Sdelphij wattron(win, color); 5571262685Sdelphij mvwprintw(win, y, x, "%s", string); 5572262685Sdelphij wattroff(win, color); 5573262685Sdelphij refresh(); 5574262685Sdelphij}</SPAN 5575262685Sdelphij></PRE 5576262685Sdelphij></DIV 5577262685Sdelphij><P 5578262685Sdelphij>This example creates a menu with a title, border, a fancy line separating title 5579262685Sdelphijand the items. As you can see, in order to attach a window to a menu the 5580262685Sdelphijfunction set_menu_win() has to be used. Then we attach the sub window also. This 5581262685Sdelphijdisplays the items in the sub window. You can also set the mark string which 5582262685Sdelphijgets displayed to the left of the selected item with set_menu_mark().</P 5583262685Sdelphij></DIV 5584262685Sdelphij><DIV 5585262685SdelphijCLASS="SECT2" 5586262685Sdelphij><HR><H3 5587262685SdelphijCLASS="SECT2" 5588262685Sdelphij><A 5589262685SdelphijNAME="SCROLLMENUS" 5590262685Sdelphij>17.5. Scrolling Menus</A 5591262685Sdelphij></H3 5592262685Sdelphij><P 5593262685Sdelphij>If the sub window given for a window is not big enough to show all the items, 5594262685Sdelphijthen the menu will be scrollable. When you are on the last item in the present 5595262685Sdelphijlist, if you send REQ_DOWN_ITEM, it gets translated into REQ_SCR_DLINE and the 5596262685Sdelphijmenu scrolls by one item. You can manually give REQ_SCR_ operations to do 5597262685Sdelphijscrolling. Let's see how it can be done.</P 5598262685Sdelphij><DIV 5599262685SdelphijCLASS="EXAMPLE" 5600262685Sdelphij><A 5601262685SdelphijNAME="MMESC" 5602262685Sdelphij></A 5603262685Sdelphij><P 5604262685Sdelphij><B 5605262685Sdelphij>Example 20. Scrolling Menus example </B 5606262685Sdelphij></P 5607262685Sdelphij><PRE 5608262685SdelphijCLASS="PROGRAMLISTING" 5609262685Sdelphij><SPAN 5610262685SdelphijCLASS="INLINEMEDIAOBJECT" 5611262685Sdelphij>#include <curses.h> 5612262685Sdelphij#include <menu.h> 5613166124Srafan 5614166124Srafan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 5615262685Sdelphij#define CTRLD 4 5616166124Srafan 5617166124Srafanchar *choices[] = { 5618166124Srafan "Choice 1", 5619166124Srafan "Choice 2", 5620166124Srafan "Choice 3", 5621166124Srafan "Choice 4", 5622262685Sdelphij "Choice 5", 5623262685Sdelphij "Choice 6", 5624262685Sdelphij "Choice 7", 5625262685Sdelphij "Choice 8", 5626262685Sdelphij "Choice 9", 5627262685Sdelphij "Choice 10", 5628166124Srafan "Exit", 5629166124Srafan (char *)NULL, 5630166124Srafan }; 5631166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 5632166124Srafan 5633166124Srafanint main() 5634262685Sdelphij{ ITEM **my_items; 5635262685Sdelphij int c; 5636262685Sdelphij MENU *my_menu; 5637166124Srafan WINDOW *my_menu_win; 5638166124Srafan int n_choices, i; 5639262685Sdelphij 5640262685Sdelphij /* Initialize curses */ 5641262685Sdelphij initscr(); 5642262685Sdelphij start_color(); 5643166124Srafan cbreak(); 5644166124Srafan noecho(); 5645262685Sdelphij keypad(stdscr, TRUE); 5646262685Sdelphij init_pair(1, COLOR_RED, COLOR_BLACK); 5647262685Sdelphij init_pair(2, COLOR_CYAN, COLOR_BLACK); 5648166124Srafan 5649262685Sdelphij /* Create items */ 5650166124Srafan n_choices = ARRAY_SIZE(choices); 5651166124Srafan my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *)); 5652262685Sdelphij for(i = 0; i < n_choices; ++i) 5653166124Srafan my_items[i] = new_item(choices[i], choices[i]); 5654166124Srafan 5655262685Sdelphij /* Crate menu */ 5656262685Sdelphij my_menu = new_menu((ITEM **)my_items); 5657166124Srafan 5658262685Sdelphij /* Create the window to be associated with the menu */ 5659166124Srafan my_menu_win = newwin(10, 40, 4, 4); 5660166124Srafan keypad(my_menu_win, TRUE); 5661166124Srafan 5662262685Sdelphij /* Set main window and sub window */ 5663166124Srafan set_menu_win(my_menu, my_menu_win); 5664166124Srafan set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1)); 5665262685Sdelphij set_menu_format(my_menu, 5, 1); 5666262685Sdelphij 5667262685Sdelphij /* Set menu mark to the string " * " */ 5668166124Srafan set_menu_mark(my_menu, " * "); 5669166124Srafan 5670262685Sdelphij /* Print a border around the main window and print a title */ 5671166124Srafan box(my_menu_win, 0, 0); 5672262685Sdelphij print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1)); 5673262685Sdelphij mvwaddch(my_menu_win, 2, 0, ACS_LTEE); 5674262685Sdelphij mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38); 5675262685Sdelphij mvwaddch(my_menu_win, 2, 39, ACS_RTEE); 5676166124Srafan 5677262685Sdelphij /* Post the menu */ 5678262685Sdelphij post_menu(my_menu); 5679262685Sdelphij wrefresh(my_menu_win); 5680262685Sdelphij 5681262685Sdelphij attron(COLOR_PAIR(2)); 5682262685Sdelphij mvprintw(LINES - 2, 0, "Use PageUp and PageDown to scoll down or up a page of items"); 5683262685Sdelphij mvprintw(LINES - 1, 0, "Arrow Keys to navigate (F1 to Exit)"); 5684262685Sdelphij attroff(COLOR_PAIR(2)); 5685262685Sdelphij refresh(); 5686166124Srafan 5687262685Sdelphij while((c = wgetch(my_menu_win)) != KEY_F(1)) 5688262685Sdelphij { switch(c) 5689262685Sdelphij { case KEY_DOWN: 5690262685Sdelphij menu_driver(my_menu, REQ_DOWN_ITEM); 5691262685Sdelphij break; 5692262685Sdelphij case KEY_UP: 5693262685Sdelphij menu_driver(my_menu, REQ_UP_ITEM); 5694262685Sdelphij break; 5695262685Sdelphij case KEY_NPAGE: 5696262685Sdelphij menu_driver(my_menu, REQ_SCR_DPAGE); 5697262685Sdelphij break; 5698262685Sdelphij case KEY_PPAGE: 5699262685Sdelphij menu_driver(my_menu, REQ_SCR_UPAGE); 5700262685Sdelphij break; 5701262685Sdelphij } 5702166124Srafan wrefresh(my_menu_win); 5703262685Sdelphij } 5704166124Srafan 5705262685Sdelphij /* Unpost and free all the memory taken up */ 5706166124Srafan unpost_menu(my_menu); 5707166124Srafan free_menu(my_menu); 5708262685Sdelphij for(i = 0; i < n_choices; ++i) 5709166124Srafan free_item(my_items[i]); 5710262685Sdelphij endwin(); 5711166124Srafan} 5712166124Srafan 5713166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 5714262685Sdelphij{ int length, x, y; 5715262685Sdelphij float temp; 5716166124Srafan 5717262685Sdelphij if(win == NULL) 5718262685Sdelphij win = stdscr; 5719262685Sdelphij getyx(win, y, x); 5720262685Sdelphij if(startx != 0) 5721262685Sdelphij x = startx; 5722262685Sdelphij if(starty != 0) 5723262685Sdelphij y = starty; 5724262685Sdelphij if(width == 0) 5725262685Sdelphij width = 80; 5726166124Srafan 5727262685Sdelphij length = strlen(string); 5728262685Sdelphij temp = (width - length)/ 2; 5729262685Sdelphij x = startx + (int)temp; 5730262685Sdelphij wattron(win, color); 5731262685Sdelphij mvwprintw(win, y, x, "%s", string); 5732262685Sdelphij wattroff(win, color); 5733262685Sdelphij refresh(); 5734262685Sdelphij}</SPAN 5735262685Sdelphij></PRE 5736262685Sdelphij></DIV 5737262685Sdelphij><P 5738262685Sdelphij>This program is self-explanatory. In this example the number of choices has been 5739262685Sdelphijincreased to ten, which is larger than our sub window size which can hold 6 5740262685Sdelphijitems. This message has to be explicitly conveyed to the menu system with the 5741262685Sdelphijfunction set_menu_format(). In here we specify the number of rows and columns we 5742262685Sdelphijwant to be displayed for a single page. We can specify any number of items to be 5743262685Sdelphijshown, in the rows variables, if it is less than the height of the sub window. 5744262685SdelphijIf the key pressed by the user is a PAGE UP or PAGE DOWN, the menu is scrolled a 5745262685Sdelphijpage due to the requests (REQ_SCR_DPAGE and REQ_SCR_UPAGE) given to 5746262685Sdelphijmenu_driver().</P 5747262685Sdelphij></DIV 5748262685Sdelphij><DIV 5749262685SdelphijCLASS="SECT2" 5750262685Sdelphij><HR><H3 5751262685SdelphijCLASS="SECT2" 5752262685Sdelphij><A 5753262685SdelphijNAME="MULTICOLUMN" 5754262685Sdelphij>17.6. Multi Columnar Menus</A 5755262685Sdelphij></H3 5756262685Sdelphij><P 5757262685Sdelphij>In the above example you have seen how to use the function set_menu_format(). I 5758262685Sdelphijdidn't mention what the cols variable (third parameter) does. Well, If your sub 5759262685Sdelphijwindow is wide enough, you can opt to display more than one item per row. This 5760262685Sdelphijcan be specified in the cols variable. To make things simpler, the following 5761262685Sdelphijexample doesn't show descriptions for the items.</P 5762262685Sdelphij><DIV 5763262685SdelphijCLASS="EXAMPLE" 5764262685Sdelphij><A 5765262685SdelphijNAME="MMEMUCO" 5766262685Sdelphij></A 5767262685Sdelphij><P 5768262685Sdelphij><B 5769262685Sdelphij>Example 21. Milt Columnar Menus Example </B 5770262685Sdelphij></P 5771262685Sdelphij><PRE 5772262685SdelphijCLASS="PROGRAMLISTING" 5773262685Sdelphij><SPAN 5774262685SdelphijCLASS="INLINEMEDIAOBJECT" 5775262685Sdelphij>#include <curses.h> 5776262685Sdelphij#include <menu.h> 5777166124Srafan 5778166124Srafan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 5779262685Sdelphij#define CTRLD 4 5780166124Srafan 5781166124Srafanchar *choices[] = { 5782166124Srafan "Choice 1", "Choice 2", "Choice 3", "Choice 4", "Choice 5", 5783262685Sdelphij "Choice 6", "Choice 7", "Choice 8", "Choice 9", "Choice 10", 5784262685Sdelphij "Choice 11", "Choice 12", "Choice 13", "Choice 14", "Choice 15", 5785262685Sdelphij "Choice 16", "Choice 17", "Choice 18", "Choice 19", "Choice 20", 5786166124Srafan "Exit", 5787166124Srafan (char *)NULL, 5788166124Srafan }; 5789166124Srafan 5790166124Srafanint main() 5791262685Sdelphij{ ITEM **my_items; 5792262685Sdelphij int c; 5793262685Sdelphij MENU *my_menu; 5794166124Srafan WINDOW *my_menu_win; 5795166124Srafan int n_choices, i; 5796262685Sdelphij 5797262685Sdelphij /* Initialize curses */ 5798262685Sdelphij initscr(); 5799262685Sdelphij start_color(); 5800166124Srafan cbreak(); 5801166124Srafan noecho(); 5802262685Sdelphij keypad(stdscr, TRUE); 5803262685Sdelphij init_pair(1, COLOR_RED, COLOR_BLACK); 5804262685Sdelphij init_pair(2, COLOR_CYAN, COLOR_BLACK); 5805166124Srafan 5806262685Sdelphij /* Create items */ 5807166124Srafan n_choices = ARRAY_SIZE(choices); 5808166124Srafan my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *)); 5809262685Sdelphij for(i = 0; i < n_choices; ++i) 5810166124Srafan my_items[i] = new_item(choices[i], choices[i]); 5811166124Srafan 5812262685Sdelphij /* Crate menu */ 5813262685Sdelphij my_menu = new_menu((ITEM **)my_items); 5814166124Srafan 5815262685Sdelphij /* Set menu option not to show the description */ 5816262685Sdelphij menu_opts_off(my_menu, O_SHOWDESC); 5817166124Srafan 5818262685Sdelphij /* Create the window to be associated with the menu */ 5819166124Srafan my_menu_win = newwin(10, 70, 4, 4); 5820166124Srafan keypad(my_menu_win, TRUE); 5821166124Srafan 5822262685Sdelphij /* Set main window and sub window */ 5823166124Srafan set_menu_win(my_menu, my_menu_win); 5824166124Srafan set_menu_sub(my_menu, derwin(my_menu_win, 6, 68, 3, 1)); 5825262685Sdelphij set_menu_format(my_menu, 5, 3); 5826262685Sdelphij set_menu_mark(my_menu, " * "); 5827166124Srafan 5828262685Sdelphij /* Print a border around the main window and print a title */ 5829166124Srafan box(my_menu_win, 0, 0); 5830262685Sdelphij 5831262685Sdelphij attron(COLOR_PAIR(2)); 5832262685Sdelphij mvprintw(LINES - 3, 0, "Use PageUp and PageDown to scroll"); 5833262685Sdelphij mvprintw(LINES - 2, 0, "Use Arrow Keys to navigate (F1 to Exit)"); 5834262685Sdelphij attroff(COLOR_PAIR(2)); 5835262685Sdelphij refresh(); 5836166124Srafan 5837262685Sdelphij /* Post the menu */ 5838262685Sdelphij post_menu(my_menu); 5839262685Sdelphij wrefresh(my_menu_win); 5840262685Sdelphij 5841262685Sdelphij while((c = wgetch(my_menu_win)) != KEY_F(1)) 5842262685Sdelphij { switch(c) 5843262685Sdelphij { case KEY_DOWN: 5844262685Sdelphij menu_driver(my_menu, REQ_DOWN_ITEM); 5845262685Sdelphij break; 5846262685Sdelphij case KEY_UP: 5847262685Sdelphij menu_driver(my_menu, REQ_UP_ITEM); 5848262685Sdelphij break; 5849262685Sdelphij case KEY_LEFT: 5850262685Sdelphij menu_driver(my_menu, REQ_LEFT_ITEM); 5851262685Sdelphij break; 5852262685Sdelphij case KEY_RIGHT: 5853262685Sdelphij menu_driver(my_menu, REQ_RIGHT_ITEM); 5854262685Sdelphij break; 5855262685Sdelphij case KEY_NPAGE: 5856262685Sdelphij menu_driver(my_menu, REQ_SCR_DPAGE); 5857262685Sdelphij break; 5858262685Sdelphij case KEY_PPAGE: 5859262685Sdelphij menu_driver(my_menu, REQ_SCR_UPAGE); 5860262685Sdelphij break; 5861262685Sdelphij } 5862166124Srafan wrefresh(my_menu_win); 5863262685Sdelphij } 5864166124Srafan 5865262685Sdelphij /* Unpost and free all the memory taken up */ 5866166124Srafan unpost_menu(my_menu); 5867166124Srafan free_menu(my_menu); 5868262685Sdelphij for(i = 0; i < n_choices; ++i) 5869166124Srafan free_item(my_items[i]); 5870262685Sdelphij endwin(); 5871262685Sdelphij}</SPAN 5872262685Sdelphij></PRE 5873262685Sdelphij></DIV 5874262685Sdelphij><P 5875262685Sdelphij>Watch the function call to set_menu_format(). It specifies the number of columns 5876262685Sdelphijto be 3, thus displaying 3 items per row. We have also switched off the showing 5877262685Sdelphijdescriptions with the function menu_opts_off(). There are couple of functions 5878262685Sdelphijset_menu_opts(), menu_opts_on() and menu_opts() which can be used to manipulate 5879262685Sdelphijmenu options. The following menu options can be specified.</P 5880262685Sdelphij><PRE 5881262685SdelphijCLASS="PROGRAMLISTING" 5882262685Sdelphij> O_ONEVALUE 5883166124Srafan Only one item can be selected for this menu. 5884166124Srafan 5885166124Srafan O_SHOWDESC 5886166124Srafan Display the item descriptions when the menu is 5887166124Srafan posted. 5888166124Srafan 5889166124Srafan O_ROWMAJOR 5890166124Srafan Display the menu in row-major order. 5891166124Srafan 5892166124Srafan O_IGNORECASE 5893166124Srafan Ignore the case when pattern-matching. 5894166124Srafan 5895166124Srafan O_SHOWMATCH 5896166124Srafan Move the cursor to within the item name while pat­ 5897166124Srafan tern-matching. 5898166124Srafan 5899166124Srafan O_NONCYCLIC 5900166124Srafan Don't wrap around next-item and previous-item, 5901262685Sdelphij requests to the other end of the menu.</PRE 5902262685Sdelphij><P 5903262685Sdelphij>All options are on by default. You can switch specific attributes on or off with 5904262685Sdelphijmenu_opts_on() and menu_opts_off() functions. You can also use set_menu_opts() 5905262685Sdelphijto directly specify the options. The argument to this function should be a OR ed 5906262685Sdelphijvalue of some of those above constants. The function menu_opts() can be used to 5907262685Sdelphijfind out a menu's present options. </P 5908262685Sdelphij></DIV 5909262685Sdelphij><DIV 5910262685SdelphijCLASS="SECT2" 5911262685Sdelphij><HR><H3 5912262685SdelphijCLASS="SECT2" 5913262685Sdelphij><A 5914262685SdelphijNAME="MULTIVALUEMENUS" 5915262685Sdelphij>17.7. Multi Valued Menus</A 5916262685Sdelphij></H3 5917262685Sdelphij><P 5918262685Sdelphij>You might be wondering what if you switch off the option O_ONEVALUE. Then the 5919262685Sdelphijmenu becomes multi-valued. That means you can select more than one item. This 5920262685Sdelphijbrings us to the request REQ_TOGGLE_ITEM. Let's see it in action.</P 5921262685Sdelphij><DIV 5922262685SdelphijCLASS="EXAMPLE" 5923262685Sdelphij><A 5924262685SdelphijNAME="MMETO" 5925262685Sdelphij></A 5926262685Sdelphij><P 5927262685Sdelphij><B 5928262685Sdelphij>Example 22. Multi Valued Menus example </B 5929262685Sdelphij></P 5930262685Sdelphij><PRE 5931262685SdelphijCLASS="PROGRAMLISTING" 5932262685Sdelphij><SPAN 5933262685SdelphijCLASS="INLINEMEDIAOBJECT" 5934262685Sdelphij>#include <curses.h> 5935262685Sdelphij#include <menu.h> 5936166124Srafan 5937166124Srafan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 5938262685Sdelphij#define CTRLD 4 5939166124Srafan 5940166124Srafanchar *choices[] = { 5941166124Srafan "Choice 1", 5942166124Srafan "Choice 2", 5943166124Srafan "Choice 3", 5944166124Srafan "Choice 4", 5945262685Sdelphij "Choice 5", 5946262685Sdelphij "Choice 6", 5947262685Sdelphij "Choice 7", 5948166124Srafan "Exit", 5949166124Srafan }; 5950166124Srafan 5951166124Srafanint main() 5952262685Sdelphij{ ITEM **my_items; 5953262685Sdelphij int c; 5954262685Sdelphij MENU *my_menu; 5955166124Srafan int n_choices, i; 5956262685Sdelphij ITEM *cur_item; 5957262685Sdelphij 5958262685Sdelphij /* Initialize curses */ 5959262685Sdelphij initscr(); 5960166124Srafan cbreak(); 5961166124Srafan noecho(); 5962262685Sdelphij keypad(stdscr, TRUE); 5963166124Srafan 5964262685Sdelphij /* Initialize items */ 5965166124Srafan n_choices = ARRAY_SIZE(choices); 5966166124Srafan my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *)); 5967262685Sdelphij for(i = 0; i < n_choices; ++i) 5968166124Srafan my_items[i] = new_item(choices[i], choices[i]); 5969262685Sdelphij my_items[n_choices] = (ITEM *)NULL; 5970166124Srafan 5971262685Sdelphij my_menu = new_menu((ITEM **)my_items); 5972166124Srafan 5973262685Sdelphij /* Make the menu multi valued */ 5974262685Sdelphij menu_opts_off(my_menu, O_ONEVALUE); 5975166124Srafan 5976262685Sdelphij mvprintw(LINES - 3, 0, "Use <SPACE> to select or unselect an item."); 5977262685Sdelphij mvprintw(LINES - 2, 0, "<ENTER> to see presently selected items(F1 to Exit)"); 5978262685Sdelphij post_menu(my_menu); 5979262685Sdelphij refresh(); 5980166124Srafan 5981262685Sdelphij while((c = getch()) != KEY_F(1)) 5982262685Sdelphij { switch(c) 5983262685Sdelphij { case KEY_DOWN: 5984262685Sdelphij menu_driver(my_menu, REQ_DOWN_ITEM); 5985262685Sdelphij break; 5986262685Sdelphij case KEY_UP: 5987262685Sdelphij menu_driver(my_menu, REQ_UP_ITEM); 5988262685Sdelphij break; 5989262685Sdelphij case ' ': 5990262685Sdelphij menu_driver(my_menu, REQ_TOGGLE_ITEM); 5991262685Sdelphij break; 5992262685Sdelphij case 10: /* Enter */ 5993262685Sdelphij { char temp[200]; 5994262685Sdelphij ITEM **items; 5995166124Srafan 5996262685Sdelphij items = menu_items(my_menu); 5997262685Sdelphij temp[0] = '\0'; 5998262685Sdelphij for(i = 0; i < item_count(my_menu); ++i) 5999262685Sdelphij if(item_value(items[i]) == TRUE) 6000262685Sdelphij { strcat(temp, item_name(items[i])); 6001262685Sdelphij strcat(temp, " "); 6002262685Sdelphij } 6003262685Sdelphij move(20, 0); 6004262685Sdelphij clrtoeol(); 6005262685Sdelphij mvprintw(20, 0, temp); 6006262685Sdelphij refresh(); 6007262685Sdelphij } 6008262685Sdelphij break; 6009262685Sdelphij } 6010262685Sdelphij } 6011166124Srafan 6012262685Sdelphij free_item(my_items[0]); 6013166124Srafan free_item(my_items[1]); 6014262685Sdelphij free_menu(my_menu); 6015262685Sdelphij endwin(); 6016166124Srafan} 6017262685Sdelphij </SPAN 6018262685Sdelphij></PRE 6019262685Sdelphij></DIV 6020262685Sdelphij><P 6021262685Sdelphij>Whew, A lot of new functions. Let's take them one after another. Firstly, the 6022262685SdelphijREQ_TOGGLE_ITEM. In a multi-valued menu, the user should be allowed to select 6023262685Sdelphijor un select more than one item. The request REQ_TOGGLE_ITEM toggles the present 6024262685Sdelphijselection. In this case when space is pressed REQ_TOGGLE_ITEM request is sent to 6025262685Sdelphijmenu_driver to achieve the result.</P 6026262685Sdelphij><P 6027262685Sdelphij>Now when the user presses <ENTER> we show the items he presently selected. 6028262685SdelphijFirst we find out the items associated with the menu using the function 6029262685Sdelphijmenu_items(). Then we loop through the items to find out if the item is selected 6030262685Sdelphijor not. The function item_value() returns TRUE if an item is selected. The 6031262685Sdelphijfunction item_count() returns the number of items in the menu. The item name can 6032262685Sdelphijbe found with item_name(). You can also find the description associated with an 6033262685Sdelphijitem using item_description().</P 6034262685Sdelphij></DIV 6035262685Sdelphij><DIV 6036262685SdelphijCLASS="SECT2" 6037262685Sdelphij><HR><H3 6038262685SdelphijCLASS="SECT2" 6039262685Sdelphij><A 6040262685SdelphijNAME="MENUOPT" 6041262685Sdelphij>17.8. Menu Options</A 6042262685Sdelphij></H3 6043262685Sdelphij><P 6044262685Sdelphij>Well, by this time you must be itching for some difference in your menu, with 6045262685Sdelphijlots of functionality. I know. You want Colors !!!. You want to create nice 6046262685Sdelphijmenus similar to those text mode <A 6047262685SdelphijHREF="http://www.jersey.net/~debinjoe/games/" 6048262685SdelphijTARGET="_top" 6049262685Sdelphij>dos games</A 6050262685Sdelphij>. The functions 6051262685Sdelphijset_menu_fore() and set_menu_back() can be used to change the attribute of the 6052262685Sdelphijselected item and unselected item. The names are misleading. They don't change 6053262685Sdelphijmenu's foreground or background which would have been useless. </P 6054262685Sdelphij><P 6055262685Sdelphij>The function set_menu_grey() can be used to set the display attribute for the 6056262685Sdelphijnon-selectable items in the menu. This brings us to the interesting option for 6057262685Sdelphijan item the one and only O_SELECTABLE. We can turn it off by the function 6058262685Sdelphijitem_opts_off() and after that that item is not selectable. It's like a grayed 6059262685Sdelphijitem in those fancy windows menus. Let's put these concepts in practice with 6060262685Sdelphijthis example</P 6061262685Sdelphij><DIV 6062262685SdelphijCLASS="EXAMPLE" 6063262685Sdelphij><A 6064262685SdelphijNAME="MMEAT" 6065262685Sdelphij></A 6066262685Sdelphij><P 6067262685Sdelphij><B 6068262685Sdelphij>Example 23. Menu Options example </B 6069262685Sdelphij></P 6070262685Sdelphij><PRE 6071262685SdelphijCLASS="PROGRAMLISTING" 6072262685Sdelphij><SPAN 6073262685SdelphijCLASS="INLINEMEDIAOBJECT" 6074262685Sdelphij>#include <menu.h> 6075166124Srafan 6076166124Srafan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 6077262685Sdelphij#define CTRLD 4 6078166124Srafan 6079166124Srafanchar *choices[] = { 6080166124Srafan "Choice 1", 6081166124Srafan "Choice 2", 6082166124Srafan "Choice 3", 6083166124Srafan "Choice 4", 6084262685Sdelphij "Choice 5", 6085262685Sdelphij "Choice 6", 6086262685Sdelphij "Choice 7", 6087166124Srafan "Exit", 6088166124Srafan }; 6089166124Srafan 6090166124Srafanint main() 6091262685Sdelphij{ ITEM **my_items; 6092262685Sdelphij int c; 6093262685Sdelphij MENU *my_menu; 6094166124Srafan int n_choices, i; 6095262685Sdelphij ITEM *cur_item; 6096262685Sdelphij 6097262685Sdelphij /* Initialize curses */ 6098262685Sdelphij initscr(); 6099262685Sdelphij start_color(); 6100166124Srafan cbreak(); 6101166124Srafan noecho(); 6102262685Sdelphij keypad(stdscr, TRUE); 6103262685Sdelphij init_pair(1, COLOR_RED, COLOR_BLACK); 6104262685Sdelphij init_pair(2, COLOR_GREEN, COLOR_BLACK); 6105262685Sdelphij init_pair(3, COLOR_MAGENTA, COLOR_BLACK); 6106166124Srafan 6107262685Sdelphij /* Initialize items */ 6108166124Srafan n_choices = ARRAY_SIZE(choices); 6109166124Srafan my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *)); 6110262685Sdelphij for(i = 0; i < n_choices; ++i) 6111166124Srafan my_items[i] = new_item(choices[i], choices[i]); 6112262685Sdelphij my_items[n_choices] = (ITEM *)NULL; 6113262685Sdelphij item_opts_off(my_items[3], O_SELECTABLE); 6114262685Sdelphij item_opts_off(my_items[6], O_SELECTABLE); 6115166124Srafan 6116262685Sdelphij /* Create menu */ 6117262685Sdelphij my_menu = new_menu((ITEM **)my_items); 6118166124Srafan 6119262685Sdelphij /* Set fore ground and back ground of the menu */ 6120262685Sdelphij set_menu_fore(my_menu, COLOR_PAIR(1) | A_REVERSE); 6121262685Sdelphij set_menu_back(my_menu, COLOR_PAIR(2)); 6122262685Sdelphij set_menu_grey(my_menu, COLOR_PAIR(3)); 6123166124Srafan 6124262685Sdelphij /* Post the menu */ 6125262685Sdelphij mvprintw(LINES - 3, 0, "Press <ENTER> to see the option selected"); 6126262685Sdelphij mvprintw(LINES - 2, 0, "Up and Down arrow keys to naviage (F1 to Exit)"); 6127262685Sdelphij post_menu(my_menu); 6128262685Sdelphij refresh(); 6129166124Srafan 6130262685Sdelphij while((c = getch()) != KEY_F(1)) 6131262685Sdelphij { switch(c) 6132262685Sdelphij { case KEY_DOWN: 6133262685Sdelphij menu_driver(my_menu, REQ_DOWN_ITEM); 6134262685Sdelphij break; 6135262685Sdelphij case KEY_UP: 6136262685Sdelphij menu_driver(my_menu, REQ_UP_ITEM); 6137262685Sdelphij break; 6138262685Sdelphij case 10: /* Enter */ 6139262685Sdelphij move(20, 0); 6140262685Sdelphij clrtoeol(); 6141262685Sdelphij mvprintw(20, 0, "Item selected is : %s", 6142262685Sdelphij item_name(current_item(my_menu))); 6143262685Sdelphij pos_menu_cursor(my_menu); 6144262685Sdelphij break; 6145262685Sdelphij } 6146262685Sdelphij } 6147262685Sdelphij unpost_menu(my_menu); 6148262685Sdelphij for(i = 0; i < n_choices; ++i) 6149262685Sdelphij free_item(my_items[i]); 6150262685Sdelphij free_menu(my_menu); 6151262685Sdelphij endwin(); 6152166124Srafan} 6153262685Sdelphij </SPAN 6154262685Sdelphij></PRE 6155262685Sdelphij></DIV 6156262685Sdelphij></DIV 6157262685Sdelphij><DIV 6158262685SdelphijCLASS="SECT2" 6159262685Sdelphij><HR><H3 6160262685SdelphijCLASS="SECT2" 6161262685Sdelphij><A 6162262685SdelphijNAME="MENUUSERPTR" 6163262685Sdelphij>17.9. The useful User Pointer</A 6164262685Sdelphij></H3 6165262685Sdelphij><P 6166262685Sdelphij>We can associate a user pointer with each item in the menu. It works the same 6167262685Sdelphijway as user pointer in panels. It's not touched by menu system. You can store 6168262685Sdelphijany thing you like in that. I usually use it to store the function to be 6169262685Sdelphijexecuted when the menu option is chosen (It's selected and may be the user 6170262685Sdelphijpressed <ENTER>);</P 6171262685Sdelphij><DIV 6172262685SdelphijCLASS="EXAMPLE" 6173262685Sdelphij><A 6174262685SdelphijNAME="MMEUS" 6175262685Sdelphij></A 6176262685Sdelphij><P 6177262685Sdelphij><B 6178262685Sdelphij>Example 24. Menu User Pointer Usage </B 6179262685Sdelphij></P 6180262685Sdelphij><PRE 6181262685SdelphijCLASS="PROGRAMLISTING" 6182262685Sdelphij><SPAN 6183262685SdelphijCLASS="INLINEMEDIAOBJECT" 6184262685Sdelphij>#include <curses.h> 6185262685Sdelphij#include <menu.h> 6186166124Srafan 6187166124Srafan#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 6188262685Sdelphij#define CTRLD 4 6189166124Srafan 6190166124Srafanchar *choices[] = { 6191166124Srafan "Choice 1", 6192166124Srafan "Choice 2", 6193166124Srafan "Choice 3", 6194166124Srafan "Choice 4", 6195262685Sdelphij "Choice 5", 6196262685Sdelphij "Choice 6", 6197262685Sdelphij "Choice 7", 6198166124Srafan "Exit", 6199166124Srafan }; 6200166124Srafanvoid func(char *name); 6201166124Srafan 6202166124Srafanint main() 6203262685Sdelphij{ ITEM **my_items; 6204262685Sdelphij int c; 6205262685Sdelphij MENU *my_menu; 6206166124Srafan int n_choices, i; 6207262685Sdelphij ITEM *cur_item; 6208262685Sdelphij 6209262685Sdelphij /* Initialize curses */ 6210262685Sdelphij initscr(); 6211262685Sdelphij start_color(); 6212166124Srafan cbreak(); 6213166124Srafan noecho(); 6214262685Sdelphij keypad(stdscr, TRUE); 6215262685Sdelphij init_pair(1, COLOR_RED, COLOR_BLACK); 6216262685Sdelphij init_pair(2, COLOR_GREEN, COLOR_BLACK); 6217262685Sdelphij init_pair(3, COLOR_MAGENTA, COLOR_BLACK); 6218166124Srafan 6219262685Sdelphij /* Initialize items */ 6220166124Srafan n_choices = ARRAY_SIZE(choices); 6221166124Srafan my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *)); 6222262685Sdelphij for(i = 0; i < n_choices; ++i) 6223262685Sdelphij { my_items[i] = new_item(choices[i], choices[i]); 6224262685Sdelphij /* Set the user pointer */ 6225262685Sdelphij set_item_userptr(my_items[i], func); 6226262685Sdelphij } 6227262685Sdelphij my_items[n_choices] = (ITEM *)NULL; 6228166124Srafan 6229262685Sdelphij /* Create menu */ 6230262685Sdelphij my_menu = new_menu((ITEM **)my_items); 6231166124Srafan 6232262685Sdelphij /* Post the menu */ 6233262685Sdelphij mvprintw(LINES - 3, 0, "Press <ENTER> to see the option selected"); 6234262685Sdelphij mvprintw(LINES - 2, 0, "Up and Down arrow keys to naviage (F1 to Exit)"); 6235262685Sdelphij post_menu(my_menu); 6236262685Sdelphij refresh(); 6237166124Srafan 6238262685Sdelphij while((c = getch()) != KEY_F(1)) 6239262685Sdelphij { switch(c) 6240262685Sdelphij { case KEY_DOWN: 6241262685Sdelphij menu_driver(my_menu, REQ_DOWN_ITEM); 6242262685Sdelphij break; 6243262685Sdelphij case KEY_UP: 6244262685Sdelphij menu_driver(my_menu, REQ_UP_ITEM); 6245262685Sdelphij break; 6246262685Sdelphij case 10: /* Enter */ 6247262685Sdelphij { ITEM *cur; 6248262685Sdelphij void (*p)(char *); 6249166124Srafan 6250262685Sdelphij cur = current_item(my_menu); 6251262685Sdelphij p = item_userptr(cur); 6252262685Sdelphij p((char *)item_name(cur)); 6253262685Sdelphij pos_menu_cursor(my_menu); 6254262685Sdelphij break; 6255262685Sdelphij } 6256262685Sdelphij break; 6257262685Sdelphij } 6258262685Sdelphij } 6259262685Sdelphij unpost_menu(my_menu); 6260262685Sdelphij for(i = 0; i < n_choices; ++i) 6261262685Sdelphij free_item(my_items[i]); 6262262685Sdelphij free_menu(my_menu); 6263262685Sdelphij endwin(); 6264166124Srafan} 6265166124Srafan 6266166124Srafanvoid func(char *name) 6267262685Sdelphij{ move(20, 0); 6268262685Sdelphij clrtoeol(); 6269262685Sdelphij mvprintw(20, 0, "Item selected is : %s", name); 6270262685Sdelphij} </SPAN 6271262685Sdelphij></PRE 6272262685Sdelphij></DIV 6273262685Sdelphij></DIV 6274262685Sdelphij></DIV 6275262685Sdelphij><DIV 6276262685SdelphijCLASS="SECT1" 6277262685Sdelphij><HR><H2 6278262685SdelphijCLASS="SECT1" 6279262685Sdelphij><A 6280262685SdelphijNAME="FORMS" 6281262685Sdelphij>18. Forms Library</A 6282262685Sdelphij></H2 6283262685Sdelphij><P 6284262685Sdelphij>Well. If you have seen those forms on web pages which take input from users and 6285262685Sdelphijdo various kinds of things, you might be wondering how would any one create such 6286262685Sdelphijforms in text mode display. It's quite difficult to write those nifty forms in 6287262685Sdelphijplain ncurses. Forms library tries to provide a basic frame work to build and 6288262685Sdelphijmaintain forms with ease. It has lot of features(functions) which manage 6289262685Sdelphijvalidation, dynamic expansion of fields etc.. Let's see it in full flow.</P 6290262685Sdelphij><P 6291262685Sdelphij>A form is a collection of fields; each field can be either a label(static text) 6292262685Sdelphijor a data-entry location. The forms also library provides functions to divide 6293262685Sdelphijforms into multiple pages. </P 6294262685Sdelphij><DIV 6295262685SdelphijCLASS="SECT2" 6296262685Sdelphij><HR><H3 6297262685SdelphijCLASS="SECT2" 6298262685Sdelphij><A 6299262685SdelphijNAME="FORMBASICS" 6300262685Sdelphij>18.1. The Basics</A 6301262685Sdelphij></H3 6302262685Sdelphij><P 6303262685Sdelphij>Forms are created in much the same way as menus. First the fields related to the 6304262685Sdelphijform are created with new_field(). You can set options for the fields, so that 6305262685Sdelphijthey can be displayed with some fancy attributes, validated before the field 6306262685Sdelphijlooses focus etc.. Then the fields are attached to form. After this, the form 6307262685Sdelphijcan be posted to display and is ready to receive inputs. On the similar lines to 6308262685Sdelphijmenu_driver(), the form is manipulated with form_driver(). We can send requests 6309262685Sdelphijto form_driver to move focus to a certain field, move cursor to end of the field 6310262685Sdelphijetc.. After the user enters values in the fields and validation done, form can 6311262685Sdelphijbe unposted and memory allocated can be freed.</P 6312262685Sdelphij><P 6313262685Sdelphij>The general flow of control of a forms program looks like this. 6314262685Sdelphij 6315262685Sdelphij<P 6316262685Sdelphij></P 6317262685Sdelphij><OL 6318262685SdelphijTYPE="1" 6319262685Sdelphij><LI 6320262685Sdelphij><P 6321262685Sdelphij>Initialize curses</P 6322262685Sdelphij></LI 6323262685Sdelphij><LI 6324262685Sdelphij><P 6325262685Sdelphij>Create fields using new_field(). You can specify the height and 6326262685Sdelphijwidth of the field, and its position on the form.</P 6327262685Sdelphij></LI 6328262685Sdelphij><LI 6329262685Sdelphij><P 6330262685Sdelphij>Create the forms with new_form() by specifying the fields to be 6331262685Sdelphijattached with.</P 6332262685Sdelphij></LI 6333262685Sdelphij><LI 6334262685Sdelphij><P 6335262685Sdelphij>Post the form with form_post() and refresh the screen.</P 6336262685Sdelphij></LI 6337262685Sdelphij><LI 6338262685Sdelphij><P 6339262685Sdelphij>Process the user requests with a loop and do necessary updates 6340262685Sdelphijto form with form_driver.</P 6341262685Sdelphij></LI 6342262685Sdelphij><LI 6343262685Sdelphij><P 6344262685Sdelphij>Unpost the menu with form_unpost()</P 6345262685Sdelphij></LI 6346262685Sdelphij><LI 6347262685Sdelphij><P 6348262685Sdelphij>Free the memory allocated to menu by free_form()</P 6349262685Sdelphij></LI 6350262685Sdelphij><LI 6351262685Sdelphij><P 6352262685Sdelphij>Free the memory allocated to the items with free_field()</P 6353262685Sdelphij></LI 6354262685Sdelphij><LI 6355262685Sdelphij><P 6356262685Sdelphij>End curses</P 6357262685Sdelphij></LI 6358262685Sdelphij></OL 6359262685Sdelphij></P 6360262685Sdelphij><P 6361262685Sdelphij>As you can see, working with forms library is much similar to handling menu 6362262685Sdelphijlibrary. The following examples will explore various aspects of form 6363262685Sdelphijprocessing. Let's start the journey with a simple example. first.</P 6364262685Sdelphij></DIV 6365262685Sdelphij><DIV 6366262685SdelphijCLASS="SECT2" 6367262685Sdelphij><HR><H3 6368262685SdelphijCLASS="SECT2" 6369262685Sdelphij><A 6370262685SdelphijNAME="COMPILEFORMS" 6371262685Sdelphij>18.2. Compiling With the Forms Library</A 6372262685Sdelphij></H3 6373262685Sdelphij><P 6374262685Sdelphij>To use forms library functions, you have to include form.h and to link the 6375262685Sdelphijprogram with forms library the flag -lform should be added along with -lncurses 6376262685Sdelphijin that order.</P 6377262685Sdelphij><PRE 6378262685SdelphijCLASS="PROGRAMLISTING" 6379262685Sdelphij> #include <form.h> 6380166124Srafan . 6381166124Srafan . 6382166124Srafan . 6383166124Srafan 6384262685Sdelphij compile and link: gcc <program file> -lform -lncurses</PRE 6385262685Sdelphij><DIV 6386262685SdelphijCLASS="EXAMPLE" 6387262685Sdelphij><A 6388262685SdelphijNAME="FFOSI" 6389262685Sdelphij></A 6390262685Sdelphij><P 6391262685Sdelphij><B 6392262685Sdelphij>Example 25. Forms Basics </B 6393262685Sdelphij></P 6394262685Sdelphij><PRE 6395262685SdelphijCLASS="PROGRAMLISTING" 6396262685Sdelphij><SPAN 6397262685SdelphijCLASS="INLINEMEDIAOBJECT" 6398262685Sdelphij>#include <form.h> 6399166124Srafan 6400166124Srafanint main() 6401262685Sdelphij{ FIELD *field[3]; 6402262685Sdelphij FORM *my_form; 6403262685Sdelphij int ch; 6404262685Sdelphij 6405262685Sdelphij /* Initialize curses */ 6406262685Sdelphij initscr(); 6407262685Sdelphij cbreak(); 6408262685Sdelphij noecho(); 6409262685Sdelphij keypad(stdscr, TRUE); 6410166124Srafan 6411262685Sdelphij /* Initialize the fields */ 6412262685Sdelphij field[0] = new_field(1, 10, 4, 18, 0, 0); 6413262685Sdelphij field[1] = new_field(1, 10, 6, 18, 0, 0); 6414262685Sdelphij field[2] = NULL; 6415166124Srafan 6416262685Sdelphij /* Set field options */ 6417262685Sdelphij set_field_back(field[0], A_UNDERLINE); /* Print a line for the option */ 6418262685Sdelphij field_opts_off(field[0], O_AUTOSKIP); /* Don't go to next field when this */ 6419262685Sdelphij /* Field is filled up */ 6420262685Sdelphij set_field_back(field[1], A_UNDERLINE); 6421262685Sdelphij field_opts_off(field[1], O_AUTOSKIP); 6422166124Srafan 6423262685Sdelphij /* Create the form and post it */ 6424262685Sdelphij my_form = new_form(field); 6425262685Sdelphij post_form(my_form); 6426262685Sdelphij refresh(); 6427262685Sdelphij 6428262685Sdelphij mvprintw(4, 10, "Value 1:"); 6429262685Sdelphij mvprintw(6, 10, "Value 2:"); 6430262685Sdelphij refresh(); 6431166124Srafan 6432262685Sdelphij /* Loop through to get user requests */ 6433262685Sdelphij while((ch = getch()) != KEY_F(1)) 6434262685Sdelphij { switch(ch) 6435262685Sdelphij { case KEY_DOWN: 6436262685Sdelphij /* Go to next field */ 6437262685Sdelphij form_driver(my_form, REQ_NEXT_FIELD); 6438262685Sdelphij /* Go to the end of the present buffer */ 6439262685Sdelphij /* Leaves nicely at the last character */ 6440262685Sdelphij form_driver(my_form, REQ_END_LINE); 6441262685Sdelphij break; 6442262685Sdelphij case KEY_UP: 6443262685Sdelphij /* Go to previous field */ 6444262685Sdelphij form_driver(my_form, REQ_PREV_FIELD); 6445262685Sdelphij form_driver(my_form, REQ_END_LINE); 6446262685Sdelphij break; 6447262685Sdelphij default: 6448262685Sdelphij /* If this is a normal character, it gets */ 6449262685Sdelphij /* Printed */ 6450262685Sdelphij form_driver(my_form, ch); 6451262685Sdelphij break; 6452262685Sdelphij } 6453262685Sdelphij } 6454166124Srafan 6455262685Sdelphij /* Un post form and free the memory */ 6456262685Sdelphij unpost_form(my_form); 6457262685Sdelphij free_form(my_form); 6458262685Sdelphij free_field(field[0]); 6459262685Sdelphij free_field(field[1]); 6460166124Srafan 6461262685Sdelphij endwin(); 6462262685Sdelphij return 0; 6463262685Sdelphij}</SPAN 6464262685Sdelphij></PRE 6465262685Sdelphij></DIV 6466262685Sdelphij><P 6467262685Sdelphij>Above example is pretty straight forward. It creates two fields with 6468262685Sdelphij<TT 6469262685SdelphijCLASS="LITERAL" 6470262685Sdelphij>new_field()</TT 6471262685Sdelphij>. new_field() takes height, width, 6472262685Sdelphijstarty, startx, number of offscreen rows and number of additional working 6473262685Sdelphijbuffers. The fifth argument number of offscreen rows specifies how much of the 6474262685Sdelphijfield to be shown. If it is zero, the entire field is always displayed otherwise 6475262685Sdelphijthe form will be scrollable when the user accesses not displayed parts of the 6476262685Sdelphijfield. The forms library allocates one buffer per field to store the data user 6477262685Sdelphijenters. Using the last parameter to new_field() we can specify it to allocate 6478262685Sdelphijsome additional buffers. These can be used for any purpose you like.</P 6479262685Sdelphij><P 6480262685Sdelphij>After creating the fields, back ground attribute of both of them is set to an 6481262685Sdelphijunderscore with set_field_back(). The AUTOSKIP option is turned off using 6482262685Sdelphijfield_opts_off(). If this option is turned on, focus will move to the next 6483262685Sdelphijfield in the form once the active field is filled up completely.</P 6484262685Sdelphij><P 6485262685Sdelphij>After attaching the fields to the form, it is posted. Here on, user inputs are 6486262685Sdelphijprocessed in the while loop, by making corresponding requests to form_driver. 6487262685SdelphijThe details of all the requests to the form_driver() are explained later.</P 6488262685Sdelphij></DIV 6489262685Sdelphij><DIV 6490262685SdelphijCLASS="SECT2" 6491262685Sdelphij><HR><H3 6492262685SdelphijCLASS="SECT2" 6493262685Sdelphij><A 6494262685SdelphijNAME="PLAYFIELDS" 6495262685Sdelphij>18.3. Playing with Fields</A 6496262685Sdelphij></H3 6497262685Sdelphij><P 6498262685Sdelphij>Each form field is associated with a lot of attributes. They can be manipulated 6499262685Sdelphijto get the required effect and to have fun !!!. So why wait? </P 6500262685Sdelphij><DIV 6501262685SdelphijCLASS="SECT3" 6502262685Sdelphij><HR><H4 6503262685SdelphijCLASS="SECT3" 6504262685Sdelphij><A 6505262685SdelphijNAME="FETCHINFO" 6506262685Sdelphij>18.3.1. Fetching Size and Location of Field</A 6507262685Sdelphij></H4 6508262685Sdelphij><P 6509262685Sdelphij>The parameters we have given at the time of creation of a field can be retrieved 6510262685Sdelphijwith field_info(). It returns height, width, starty, startx, number of offscreen 6511262685Sdelphijrows, and number of additional buffers into the parameters given to it. It is a 6512262685Sdelphijsort of inverse of new_field().</P 6513262685Sdelphij><PRE 6514262685SdelphijCLASS="PROGRAMLISTING" 6515262685Sdelphij>int field_info( FIELD *field, /* field from which to fetch */ 6516166124Srafan int *height, *int width, /* field size */ 6517166124Srafan int *top, int *left, /* upper left corner */ 6518166124Srafan int *offscreen, /* number of offscreen rows */ 6519262685Sdelphij int *nbuf); /* number of working buffers */</PRE 6520262685Sdelphij></DIV 6521262685Sdelphij><DIV 6522262685SdelphijCLASS="SECT3" 6523262685Sdelphij><HR><H4 6524262685SdelphijCLASS="SECT3" 6525262685Sdelphij><A 6526262685SdelphijNAME="MOVEFIELD" 6527262685Sdelphij>18.3.2. Moving the field</A 6528262685Sdelphij></H4 6529262685Sdelphij><P 6530262685Sdelphij>The location of the field can be moved to a different position with 6531262685Sdelphijmove_field().</P 6532262685Sdelphij><PRE 6533262685SdelphijCLASS="PROGRAMLISTING" 6534262685Sdelphij>int move_field( FIELD *field, /* field to alter */ 6535262685Sdelphij int top, int left); /* new upper-left corner */</PRE 6536262685Sdelphij><P 6537262685Sdelphij>As usual, the changed position can be queried with field_infor().</P 6538262685Sdelphij></DIV 6539262685Sdelphij><DIV 6540262685SdelphijCLASS="SECT3" 6541262685Sdelphij><HR><H4 6542262685SdelphijCLASS="SECT3" 6543262685Sdelphij><A 6544262685SdelphijNAME="JUSTIFYFIELD" 6545262685Sdelphij>18.3.3. Field Justification</A 6546262685Sdelphij></H4 6547262685Sdelphij><P 6548262685Sdelphij>The justification to be done for the field can be fixed using the function 6549262685Sdelphijset_field_just().</P 6550262685Sdelphij><PRE 6551262685SdelphijCLASS="PROGRAMLISTING" 6552262685Sdelphij> int set_field_just(FIELD *field, /* field to alter */ 6553166124Srafan int justmode); /* mode to set */ 6554262685Sdelphij int field_just(FIELD *field); /* fetch justify mode of field */</PRE 6555262685Sdelphij><P 6556262685Sdelphij>The justification mode valued accepted and returned by these functions are 6557262685SdelphijNO_JUSTIFICATION, JUSTIFY_RIGHT, JUSTIFY_LEFT, or JUSTIFY_CENTER.</P 6558262685Sdelphij></DIV 6559262685Sdelphij><DIV 6560262685SdelphijCLASS="SECT3" 6561262685Sdelphij><HR><H4 6562262685SdelphijCLASS="SECT3" 6563262685Sdelphij><A 6564262685SdelphijNAME="FIELDDISPATTRIB" 6565262685Sdelphij>18.3.4. Field Display Attributes</A 6566262685Sdelphij></H4 6567262685Sdelphij><P 6568262685Sdelphij>As you have seen, in the above example, display attribute for the fields can be 6569262685Sdelphijset with set_field_fore() and setfield_back(). These functions set foreground 6570262685Sdelphijand background attribute of the fields. You can also specify a pad character 6571262685Sdelphijwhich will be filled in the unfilled portion of the field. The pad character is 6572262685Sdelphijset with a call to set_field_pad(). Default pad value is a space. The functions 6573262685Sdelphijfield_fore(), field_back, field_pad() can be used to query the present 6574262685Sdelphijforeground, background attributes and pad character for the field. The following 6575262685Sdelphijlist gives the usage of functions.</P 6576262685Sdelphij><PRE 6577262685SdelphijCLASS="PROGRAMLISTING" 6578262685Sdelphij> int set_field_fore(FIELD *field, /* field to alter */ 6579166124Srafan chtype attr); /* attribute to set */ 6580166124Srafan 6581166124Srafanchtype field_fore(FIELD *field); /* field to query */ 6582166124Srafan /* returns foreground attribute */ 6583166124Srafan 6584166124Srafanint set_field_back(FIELD *field, /* field to alter */ 6585166124Srafan chtype attr); /* attribute to set */ 6586166124Srafan 6587166124Srafanchtype field_back(FIELD *field); /* field to query */ 6588166124Srafan /* returns background attribute */ 6589166124Srafan 6590166124Srafanint set_field_pad(FIELD *field, /* field to alter */ 6591166124Srafan int pad); /* pad character to set */ 6592166124Srafan 6593166124Srafanchtype field_pad(FIELD *field); /* field to query */ 6594262685Sdelphij /* returns present pad character */ </PRE 6595262685Sdelphij><P 6596262685Sdelphij>Though above functions seem quite simple, using colors with set_field_fore() may 6597262685Sdelphijbe frustrating in the beginning. Let me first explain about foreground and 6598262685Sdelphijbackground attributes of a field. The foreground attribute is associated with 6599262685Sdelphijthe character. That means a character in the field is printed with the attribute 6600262685Sdelphijyou have set with set_field_fore(). Background attribute is the attribute used 6601262685Sdelphijto fill background of field, whether any character is there or not. So what 6602262685Sdelphijabout colors? Since colors are always defined in pairs, what is the right way to 6603262685Sdelphijdisplay colored fields? Here's an example clarifying color attributes.</P 6604262685Sdelphij><DIV 6605262685SdelphijCLASS="EXAMPLE" 6606262685Sdelphij><A 6607262685SdelphijNAME="FFOAT" 6608262685Sdelphij></A 6609262685Sdelphij><P 6610262685Sdelphij><B 6611262685Sdelphij>Example 26. Form Attributes example </B 6612262685Sdelphij></P 6613262685Sdelphij><PRE 6614262685SdelphijCLASS="PROGRAMLISTING" 6615262685Sdelphij><SPAN 6616262685SdelphijCLASS="INLINEMEDIAOBJECT" 6617262685Sdelphij>#include <form.h> 6618166124Srafan 6619166124Srafanint main() 6620262685Sdelphij{ FIELD *field[3]; 6621262685Sdelphij FORM *my_form; 6622262685Sdelphij int ch; 6623262685Sdelphij 6624262685Sdelphij /* Initialize curses */ 6625262685Sdelphij initscr(); 6626262685Sdelphij start_color(); 6627262685Sdelphij cbreak(); 6628262685Sdelphij noecho(); 6629262685Sdelphij keypad(stdscr, TRUE); 6630166124Srafan 6631262685Sdelphij /* Initialize few color pairs */ 6632262685Sdelphij init_pair(1, COLOR_WHITE, COLOR_BLUE); 6633262685Sdelphij init_pair(2, COLOR_WHITE, COLOR_BLUE); 6634166124Srafan 6635262685Sdelphij /* Initialize the fields */ 6636262685Sdelphij field[0] = new_field(1, 10, 4, 18, 0, 0); 6637262685Sdelphij field[1] = new_field(1, 10, 6, 18, 0, 0); 6638262685Sdelphij field[2] = NULL; 6639166124Srafan 6640262685Sdelphij /* Set field options */ 6641262685Sdelphij set_field_fore(field[0], COLOR_PAIR(1));/* Put the field with blue background */ 6642262685Sdelphij set_field_back(field[0], COLOR_PAIR(2));/* and white foreground (characters */ 6643262685Sdelphij /* are printed in white */ 6644262685Sdelphij field_opts_off(field[0], O_AUTOSKIP); /* Don't go to next field when this */ 6645262685Sdelphij /* Field is filled up */ 6646262685Sdelphij set_field_back(field[1], A_UNDERLINE); 6647262685Sdelphij field_opts_off(field[1], O_AUTOSKIP); 6648166124Srafan 6649262685Sdelphij /* Create the form and post it */ 6650262685Sdelphij my_form = new_form(field); 6651262685Sdelphij post_form(my_form); 6652262685Sdelphij refresh(); 6653262685Sdelphij 6654262685Sdelphij set_current_field(my_form, field[0]); /* Set focus to the colored field */ 6655262685Sdelphij mvprintw(4, 10, "Value 1:"); 6656262685Sdelphij mvprintw(6, 10, "Value 2:"); 6657262685Sdelphij mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields"); 6658262685Sdelphij refresh(); 6659166124Srafan 6660262685Sdelphij /* Loop through to get user requests */ 6661262685Sdelphij while((ch = getch()) != KEY_F(1)) 6662262685Sdelphij { switch(ch) 6663262685Sdelphij { case KEY_DOWN: 6664262685Sdelphij /* Go to next field */ 6665262685Sdelphij form_driver(my_form, REQ_NEXT_FIELD); 6666262685Sdelphij /* Go to the end of the present buffer */ 6667262685Sdelphij /* Leaves nicely at the last character */ 6668262685Sdelphij form_driver(my_form, REQ_END_LINE); 6669262685Sdelphij break; 6670262685Sdelphij case KEY_UP: 6671262685Sdelphij /* Go to previous field */ 6672262685Sdelphij form_driver(my_form, REQ_PREV_FIELD); 6673262685Sdelphij form_driver(my_form, REQ_END_LINE); 6674262685Sdelphij break; 6675262685Sdelphij default: 6676262685Sdelphij /* If this is a normal character, it gets */ 6677262685Sdelphij /* Printed */ 6678262685Sdelphij form_driver(my_form, ch); 6679262685Sdelphij break; 6680262685Sdelphij } 6681262685Sdelphij } 6682166124Srafan 6683262685Sdelphij /* Un post form and free the memory */ 6684262685Sdelphij unpost_form(my_form); 6685262685Sdelphij free_form(my_form); 6686262685Sdelphij free_field(field[0]); 6687262685Sdelphij free_field(field[1]); 6688166124Srafan 6689262685Sdelphij endwin(); 6690262685Sdelphij return 0; 6691262685Sdelphij}</SPAN 6692262685Sdelphij></PRE 6693262685Sdelphij></DIV 6694262685Sdelphij><P 6695262685Sdelphij>Play with the color pairs and try to understand the foreground and background 6696262685Sdelphijattributes. In my programs using color attributes, I usually set only the 6697262685Sdelphijbackground with set_field_back(). Curses simply doesn't allow defining 6698262685Sdelphijindividual color attributes. </P 6699262685Sdelphij></DIV 6700262685Sdelphij><DIV 6701262685SdelphijCLASS="SECT3" 6702262685Sdelphij><HR><H4 6703262685SdelphijCLASS="SECT3" 6704262685Sdelphij><A 6705262685SdelphijNAME="FIELDOPTIONBITS" 6706262685Sdelphij>18.3.5. Field Option Bits</A 6707262685Sdelphij></H4 6708262685Sdelphij><P 6709262685Sdelphij>There is also a large collection of field option bits you can set to control 6710262685Sdelphijvarious aspects of forms processing. You can manipulate them with these 6711262685Sdelphijfunctions:</P 6712262685Sdelphij><PRE 6713262685SdelphijCLASS="PROGRAMLISTING" 6714262685Sdelphij>int set_field_opts(FIELD *field, /* field to alter */ 6715166124Srafan int attr); /* attribute to set */ 6716166124Srafan 6717166124Srafanint field_opts_on(FIELD *field, /* field to alter */ 6718166124Srafan int attr); /* attributes to turn on */ 6719166124Srafan 6720166124Srafanint field_opts_off(FIELD *field, /* field to alter */ 6721166124Srafan int attr); /* attributes to turn off */ 6722166124Srafan 6723262685Sdelphijint field_opts(FIELD *field); /* field to query */ </PRE 6724262685Sdelphij><P 6725262685Sdelphij>The function set_field_opts() can be used to directly set attributes of a field 6726262685Sdelphijor you can choose to switch a few attributes on and off with field_opts_on() and 6727262685Sdelphijfield_opts_off() selectively. Anytime you can query the attributes of a field 6728262685Sdelphijwith field_opts(). The following is the list of available options. By default, 6729262685Sdelphijall options are on.</P 6730262685Sdelphij><P 6731262685Sdelphij></P 6732262685Sdelphij><DIV 6733262685SdelphijCLASS="VARIABLELIST" 6734262685Sdelphij><DL 6735262685Sdelphij><DT 6736262685Sdelphij>O_VISIBLE</DT 6737262685Sdelphij><DD 6738262685Sdelphij><P 6739262685Sdelphij>Controls whether the field is visible on the screen. Can be used 6740262685Sdelphijduring form processing to hide or pop up fields depending on the value 6741262685Sdelphijof parent fields.</P 6742262685Sdelphij></DD 6743262685Sdelphij><DT 6744262685Sdelphij>O_ACTIVE</DT 6745262685Sdelphij><DD 6746262685Sdelphij><P 6747262685Sdelphij>Controls whether the field is active during forms processing (i.e. 6748262685Sdelphijvisited by form navigation keys). Can be used to make labels or derived 6749262685Sdelphijfields with buffer values alterable by the forms application, not the user.</P 6750262685Sdelphij></DD 6751262685Sdelphij><DT 6752262685Sdelphij>O_PUBLIC</DT 6753262685Sdelphij><DD 6754262685Sdelphij><P 6755262685Sdelphij>Controls whether data is displayed during field entry. If this option is 6756262685Sdelphijturned off on a field, the library will accept and edit data in that field, 6757262685Sdelphijbut it will not be displayed and the visible field cursor will not move. 6758262685SdelphijYou can turn off the O_PUBLIC bit to define password fields.</P 6759262685Sdelphij></DD 6760262685Sdelphij><DT 6761262685Sdelphij>O_EDIT</DT 6762262685Sdelphij><DD 6763262685Sdelphij><P 6764262685Sdelphij>Controls whether the field's data can be modified. When this option is 6765262685Sdelphijoff, all editing requests except <TT 6766262685SdelphijCLASS="LITERAL" 6767262685Sdelphij>REQ_PREV_CHOICE</TT 6768262685Sdelphij> and <TT 6769262685SdelphijCLASS="LITERAL" 6770262685Sdelphij>REQ_NEXT_CHOICE</TT 6771262685Sdelphij>will 6772262685Sdelphijfail. Such read-only fields may be useful for help messages.</P 6773262685Sdelphij></DD 6774262685Sdelphij><DT 6775262685Sdelphij>O_WRAP</DT 6776262685Sdelphij><DD 6777262685Sdelphij><P 6778262685Sdelphij>Controls word-wrapping in multi-line fields. Normally, when any 6779262685Sdelphijcharacter of a (blank-separated) word reaches the end of the current line, the 6780262685Sdelphijentire word is wrapped to the next line (assuming there is one). When this 6781262685Sdelphijoption is off, the word will be split across the line break.</P 6782262685Sdelphij></DD 6783262685Sdelphij><DT 6784262685Sdelphij>O_BLANK</DT 6785262685Sdelphij><DD 6786262685Sdelphij><P 6787262685Sdelphij>Controls field blanking. When this option is on, entering a character at 6788262685Sdelphijthe first field position erases the entire field (except for the just-entered 6789262685Sdelphijcharacter).</P 6790262685Sdelphij></DD 6791262685Sdelphij><DT 6792262685Sdelphij>O_AUTOSKIP</DT 6793262685Sdelphij><DD 6794262685Sdelphij><P 6795262685Sdelphij>Controls automatic skip to next field when this one fills. Normally, 6796262685Sdelphijwhen the forms user tries to type more data into a field than will fit, 6797262685Sdelphijthe editing location jumps to next field. When this option is off, the 6798262685Sdelphijuser's cursor will hang at the end of the field. This option is ignored 6799262685Sdelphijin dynamic fields that have not reached their size limit.</P 6800262685Sdelphij></DD 6801262685Sdelphij><DT 6802262685Sdelphij>O_NULLOK</DT 6803262685Sdelphij><DD 6804262685Sdelphij><P 6805262685Sdelphij>Controls whether validation is applied to 6806262685Sdelphijblank fields. Normally, it is not; the user can leave a field blank 6807262685Sdelphijwithout invoking the usual validation check on exit. If this option is 6808262685Sdelphijoff on a field, exit from it will invoke a validation check.</P 6809262685Sdelphij></DD 6810262685Sdelphij><DT 6811262685Sdelphij>O_PASSOK</DT 6812262685Sdelphij><DD 6813262685Sdelphij><P 6814262685Sdelphij>Controls whether validation occurs on every exit, or only after 6815262685Sdelphijthe field is modified. Normally the latter is true. Setting O_PASSOK 6816262685Sdelphijmay be useful if your field's validation function may change during 6817262685Sdelphijforms processing.</P 6818262685Sdelphij></DD 6819262685Sdelphij><DT 6820262685Sdelphij>O_STATIC</DT 6821262685Sdelphij><DD 6822262685Sdelphij><P 6823262685Sdelphij>Controls whether the field is fixed to its initial dimensions. If you 6824262685Sdelphijturn this off, the field becomes dynamic and will 6825262685Sdelphijstretch to fit entered data.</P 6826262685Sdelphij></DD 6827262685Sdelphij></DL 6828262685Sdelphij></DIV 6829262685Sdelphij><P 6830262685Sdelphij>A field's options cannot be changed while the field is currently selected. 6831262685SdelphijHowever, options may be changed on posted fields that are not current. </P 6832262685Sdelphij><P 6833262685Sdelphij>The option values are bit-masks and can be composed with logical-or in 6834262685Sdelphijthe obvious way. You have seen the usage of switching off O_AUTOSKIP option. 6835262685SdelphijThe following example clarifies usage of some more options. Other options 6836262685Sdelphijare explained where appropriate.</P 6837262685Sdelphij><DIV 6838262685SdelphijCLASS="EXAMPLE" 6839262685Sdelphij><A 6840262685SdelphijNAME="FFOOP" 6841262685Sdelphij></A 6842262685Sdelphij><P 6843262685Sdelphij><B 6844262685Sdelphij>Example 27. Field Options Usage example </B 6845262685Sdelphij></P 6846262685Sdelphij><PRE 6847262685SdelphijCLASS="PROGRAMLISTING" 6848262685Sdelphij><SPAN 6849262685SdelphijCLASS="INLINEMEDIAOBJECT" 6850262685Sdelphij>#include <form.h> 6851166124Srafan 6852166124Srafan#define STARTX 15 6853166124Srafan#define STARTY 4 6854166124Srafan#define WIDTH 25 6855166124Srafan 6856166124Srafan#define N_FIELDS 3 6857166124Srafan 6858166124Srafanint main() 6859262685Sdelphij{ FIELD *field[N_FIELDS]; 6860262685Sdelphij FORM *my_form; 6861262685Sdelphij int ch, i; 6862262685Sdelphij 6863262685Sdelphij /* Initialize curses */ 6864262685Sdelphij initscr(); 6865262685Sdelphij cbreak(); 6866262685Sdelphij noecho(); 6867262685Sdelphij keypad(stdscr, TRUE); 6868166124Srafan 6869262685Sdelphij /* Initialize the fields */ 6870262685Sdelphij for(i = 0; i < N_FIELDS - 1; ++i) 6871262685Sdelphij field[i] = new_field(1, WIDTH, STARTY + i * 2, STARTX, 0, 0); 6872262685Sdelphij field[N_FIELDS - 1] = NULL; 6873166124Srafan 6874262685Sdelphij /* Set field options */ 6875262685Sdelphij set_field_back(field[1], A_UNDERLINE); /* Print a line for the option */ 6876262685Sdelphij 6877262685Sdelphij field_opts_off(field[0], O_ACTIVE); /* This field is a static label */ 6878262685Sdelphij field_opts_off(field[1], O_PUBLIC); /* This filed is like a password field*/ 6879262685Sdelphij field_opts_off(field[1], O_AUTOSKIP); /* To avoid entering the same field */ 6880262685Sdelphij /* after last character is entered */ 6881262685Sdelphij 6882262685Sdelphij /* Create the form and post it */ 6883262685Sdelphij my_form = new_form(field); 6884262685Sdelphij post_form(my_form); 6885262685Sdelphij refresh(); 6886262685Sdelphij 6887262685Sdelphij set_field_just(field[0], JUSTIFY_CENTER); /* Center Justification */ 6888262685Sdelphij set_field_buffer(field[0], 0, "This is a static Field"); 6889262685Sdelphij /* Initialize the field */ 6890262685Sdelphij mvprintw(STARTY, STARTX - 10, "Field 1:"); 6891262685Sdelphij mvprintw(STARTY + 2, STARTX - 10, "Field 2:"); 6892262685Sdelphij refresh(); 6893166124Srafan 6894262685Sdelphij /* Loop through to get user requests */ 6895262685Sdelphij while((ch = getch()) != KEY_F(1)) 6896262685Sdelphij { switch(ch) 6897262685Sdelphij { case KEY_DOWN: 6898262685Sdelphij /* Go to next field */ 6899262685Sdelphij form_driver(my_form, REQ_NEXT_FIELD); 6900262685Sdelphij /* Go to the end of the present buffer */ 6901262685Sdelphij /* Leaves nicely at the last character */ 6902262685Sdelphij form_driver(my_form, REQ_END_LINE); 6903262685Sdelphij break; 6904262685Sdelphij case KEY_UP: 6905262685Sdelphij /* Go to previous field */ 6906262685Sdelphij form_driver(my_form, REQ_PREV_FIELD); 6907262685Sdelphij form_driver(my_form, REQ_END_LINE); 6908262685Sdelphij break; 6909262685Sdelphij default: 6910262685Sdelphij /* If this is a normal character, it gets */ 6911262685Sdelphij /* Printed */ 6912262685Sdelphij form_driver(my_form, ch); 6913262685Sdelphij break; 6914262685Sdelphij } 6915262685Sdelphij } 6916166124Srafan 6917262685Sdelphij /* Un post form and free the memory */ 6918262685Sdelphij unpost_form(my_form); 6919262685Sdelphij free_form(my_form); 6920262685Sdelphij free_field(field[0]); 6921262685Sdelphij free_field(field[1]); 6922166124Srafan 6923262685Sdelphij endwin(); 6924262685Sdelphij return 0; 6925262685Sdelphij}</SPAN 6926262685Sdelphij></PRE 6927262685Sdelphij></DIV 6928262685Sdelphij><P 6929262685Sdelphij>This example, though useless, shows the usage of options. If used properly, they 6930262685Sdelphijcan present information very effectively in a form. The second field being not 6931262685SdelphijO_PUBLIC, does not show the characters you are typing.</P 6932262685Sdelphij></DIV 6933262685Sdelphij><DIV 6934262685SdelphijCLASS="SECT3" 6935262685Sdelphij><HR><H4 6936262685SdelphijCLASS="SECT3" 6937262685Sdelphij><A 6938262685SdelphijNAME="FIELDSTATUS" 6939262685Sdelphij>18.3.6. Field Status</A 6940262685Sdelphij></H4 6941262685Sdelphij><P 6942262685Sdelphij>The field status specifies whether the field has got edited or not. It is 6943262685Sdelphijinitially set to FALSE and when user enters something and the data buffer gets 6944262685Sdelphijmodified it becomes TRUE. So a field's status can be queried to find out whether 6945262685Sdelphijit has been modified or not. The following functions can assist in those 6946262685Sdelphijoperations.</P 6947262685Sdelphij><PRE 6948262685SdelphijCLASS="PROGRAMLISTING" 6949262685Sdelphij>int set_field_status(FIELD *field, /* field to alter */ 6950166124Srafan int status); /* status to set */ 6951166124Srafan 6952262685Sdelphijint field_status(FIELD *field); /* fetch status of field */</PRE 6953262685Sdelphij><P 6954262685Sdelphij>It's better to check the field's status only after after leaving the field, as 6955262685Sdelphijdata buffer might not have been updated yet as the validation is still due. To 6956262685Sdelphijguarantee that right status is returned, call field_status() either (1) in the 6957262685Sdelphijfield's exit validation check routine, (2) from the field's or form's 6958262685Sdelphijinitialization or termination hooks, or (3) just after a REQ_VALIDATION request 6959262685Sdelphijhas been processed by the forms driver</P 6960262685Sdelphij></DIV 6961262685Sdelphij><DIV 6962262685SdelphijCLASS="SECT3" 6963262685Sdelphij><HR><H4 6964262685SdelphijCLASS="SECT3" 6965262685Sdelphij><A 6966262685SdelphijNAME="FIELDUSERPTR" 6967262685Sdelphij>18.3.7. Field User Pointer</A 6968262685Sdelphij></H4 6969262685Sdelphij><P 6970262685Sdelphij>Every field structure contains one pointer that can be used by the user for 6971262685Sdelphijvarious purposes. It is not touched by forms library and can be used for any 6972262685Sdelphijpurpose by the user. The following functions set and fetch user pointer.</P 6973262685Sdelphij><PRE 6974262685SdelphijCLASS="PROGRAMLISTING" 6975262685Sdelphij>int set_field_userptr(FIELD *field, 6976166124Srafan char *userptr); /* the user pointer you wish to associate */ 6977166124Srafan /* with the field */ 6978166124Srafan 6979262685Sdelphijchar *field_userptr(FIELD *field); /* fetch user pointer of the field */</PRE 6980262685Sdelphij></DIV 6981262685Sdelphij><DIV 6982262685SdelphijCLASS="SECT3" 6983262685Sdelphij><HR><H4 6984262685SdelphijCLASS="SECT3" 6985262685Sdelphij><A 6986262685SdelphijNAME="VARIABLESIZEFIELDS" 6987262685Sdelphij>18.3.8. Variable-Sized Fields</A 6988262685Sdelphij></H4 6989262685Sdelphij><P 6990262685Sdelphij>If you want a dynamically changing field with variable width, this is the 6991262685Sdelphijfeature you want to put to full use. This will allow the user to enter more data 6992262685Sdelphijthan the original size of the field and let the field grow. According to the 6993262685Sdelphijfield orientation it will scroll horizontally or vertically to incorporate the 6994262685Sdelphijnew data.</P 6995262685Sdelphij><P 6996262685Sdelphij>To make a field dynamically growable, the option O_STATIC should be turned off. 6997262685SdelphijThis can be done with a 6998262685Sdelphij<PRE 6999262685SdelphijCLASS="PROGRAMLISTING" 7000262685Sdelphij> field_opts_off(field_pointer, O_STATIC);</PRE 7001262685Sdelphij></P 7002262685Sdelphij><P 7003262685Sdelphij>But it's usually not advisable to allow a field to grow infinitely. You can set 7004262685Sdelphija maximum limit to the growth of the field with 7005262685Sdelphij<PRE 7006262685SdelphijCLASS="PROGRAMLISTING" 7007262685Sdelphij>int set_max_field(FIELD *field, /* Field on which to operate */ 7008262685Sdelphij int max_growth); /* maximum growth allowed for the field */</PRE 7009262685Sdelphij></P 7010262685Sdelphij><P 7011262685Sdelphij>The field info for a dynamically growable field can be retrieved by 7012262685Sdelphij<PRE 7013262685SdelphijCLASS="PROGRAMLISTING" 7014262685Sdelphij>int dynamic_field_info( FIELD *field, /* Field on which to operate */ 7015166124Srafan int *prows, /* number of rows will be filled in this */ 7016166124Srafan int *pcols, /* number of columns will be filled in this*/ 7017166124Srafan int *pmax) /* maximum allowable growth will be filled */ 7018262685Sdelphij /* in this */</PRE 7019262685Sdelphij> 7020262685SdelphijThough field_info work as usual, it is advisable to use this function to get the 7021262685Sdelphijproper attributes of a dynamically growable field.</P 7022262685Sdelphij><P 7023262685Sdelphij>Recall the library routine new_field; a new field created with height set to one 7024262685Sdelphijwill be defined to be a one line field. A new field created with height greater 7025262685Sdelphijthan one will be defined to be a multi line field. </P 7026262685Sdelphij><P 7027262685Sdelphij>A one line field with O_STATIC turned off (dynamically growable field) will 7028262685Sdelphijcontain a single fixed row, but the number of columns can increase if the user 7029262685Sdelphijenters more data than the initial field will hold. The number of columns 7030262685Sdelphijdisplayed will remain fixed and the additional data will scroll horizontally. </P 7031262685Sdelphij><P 7032262685Sdelphij>A multi line field with O_STATIC turned off (dynamically growable field) will 7033262685Sdelphijcontain a fixed number of columns, but the number of rows can increase if the 7034262685Sdelphijuser enters more data than the initial field will hold. The number of rows 7035262685Sdelphijdisplayed will remain fixed and the additional data will scroll vertically.</P 7036262685Sdelphij><P 7037262685Sdelphij>The above two paragraphs pretty much describe a dynamically growable field's 7038262685Sdelphijbehavior. The way other parts of forms library behaves is described below:</P 7039262685Sdelphij><P 7040262685Sdelphij></P 7041262685Sdelphij><OL 7042262685SdelphijTYPE="1" 7043262685Sdelphij><LI 7044262685Sdelphij><P 7045262685Sdelphij>The field option O_AUTOSKIP will be ignored if the option O_STATIC is off and 7046262685Sdelphijthere is no maximum growth specified for the field. Currently, O_AUTOSKIP 7047262685Sdelphijgenerates an automatic REQ_NEXT_FIELD form driver request when the user types in 7048262685Sdelphijthe last character position of a field. On a growable field with no maximum 7049262685Sdelphijgrowth specified, there is no last character position. If a maximum growth is 7050262685Sdelphijspecified, the O_AUTOSKIP option will work as normal if the field has grown to 7051262685Sdelphijits maximum size. </P 7052262685Sdelphij></LI 7053262685Sdelphij><LI 7054262685Sdelphij><P 7055262685Sdelphij>The field justification will be ignored if the option O_STATIC is off. 7056262685SdelphijCurrently, set_field_just can be used to JUSTIFY_LEFT, JUSTIFY_RIGHT, 7057262685SdelphijJUSTIFY_CENTER the contents of a one line field. A growable one line field will, 7058262685Sdelphijby definition, grow and scroll horizontally and may contain more data than can 7059262685Sdelphijbe justified. The return from field_just will be unchanged. </P 7060262685Sdelphij></LI 7061262685Sdelphij><LI 7062262685Sdelphij><P 7063262685Sdelphij>The overloaded form driver request REQ_NEW_LINE will operate the same way 7064262685Sdelphijregardless of the O_NL_OVERLOAD form option if the field option O_STATIC is off 7065262685Sdelphijand there is no maximum growth specified for the field. Currently, if the form 7066262685Sdelphijoption O_NL_OVERLOAD is on, REQ_NEW_LINE implicitly generates a REQ_NEXT_FIELD 7067262685Sdelphijif called from the last line of a field. If a field can grow without bound, 7068262685Sdelphijthere is no last line, so REQ_NEW_LINE will never implicitly generate a 7069262685SdelphijREQ_NEXT_FIELD. If a maximum growth limit is specified and the O_NL_OVERLOAD 7070262685Sdelphijform option is on, REQ_NEW_LINE will only implicitly generate REQ_NEXT_FIELD if 7071262685Sdelphijthe field has grown to its maximum size and the user is on the last line. </P 7072262685Sdelphij></LI 7073262685Sdelphij><LI 7074262685Sdelphij><P 7075262685Sdelphij>The library call dup_field will work as usual; it will duplicate the field, 7076262685Sdelphijincluding the current buffer size and contents of the field being duplicated. 7077262685SdelphijAny specified maximum growth will also be duplicated. </P 7078262685Sdelphij></LI 7079262685Sdelphij><LI 7080262685Sdelphij><P 7081262685Sdelphij>The library call link_field will work as usual; it will duplicate all field 7082262685Sdelphijattributes and share buffers with the field being linked. If the O_STATIC field 7083262685Sdelphijoption is subsequently changed by a field sharing buffers, how the system reacts 7084262685Sdelphijto an attempt to enter more data into the field than the buffer will currently 7085262685Sdelphijhold will depend on the setting of the option in the current field. </P 7086262685Sdelphij></LI 7087262685Sdelphij><LI 7088262685Sdelphij><P 7089262685Sdelphij>The library call field_info will work as usual; the variable nrow will contain 7090262685Sdelphijthe value of the original call to new_field. The user should use 7091262685Sdelphijdynamic_field_info, described above, to query the current size of the buffer.</P 7092262685Sdelphij></LI 7093262685Sdelphij></OL 7094262685Sdelphij><P 7095262685Sdelphij>Some of the above points make sense only after explaining form driver. We will 7096262685Sdelphijbe looking into that in next few sections.</P 7097262685Sdelphij></DIV 7098262685Sdelphij></DIV 7099262685Sdelphij><DIV 7100262685SdelphijCLASS="SECT2" 7101262685Sdelphij><HR><H3 7102262685SdelphijCLASS="SECT2" 7103262685Sdelphij><A 7104262685SdelphijNAME="FORMWINDOWS" 7105262685Sdelphij>18.4. Form Windows</A 7106262685Sdelphij></H3 7107262685Sdelphij><P 7108262685Sdelphij>The form windows concept is pretty much similar to menu windows. Every form is 7109262685Sdelphijassociated with a main window and a sub window. The form main window displays 7110262685Sdelphijany title or border associated or whatever the user wishes. Then the sub window 7111262685Sdelphijcontains all the fields and displays them according to their position. This 7112262685Sdelphijgives the flexibility of manipulating fancy form displaying very easily. </P 7113262685Sdelphij><P 7114262685Sdelphij>Since this is pretty much similar to menu windows, I am providing an example 7115262685Sdelphijwith out much explanation. The functions are similar and they work the same way.</P 7116262685Sdelphij><DIV 7117262685SdelphijCLASS="EXAMPLE" 7118262685Sdelphij><A 7119262685SdelphijNAME="FFOWI" 7120262685Sdelphij></A 7121262685Sdelphij><P 7122262685Sdelphij><B 7123262685Sdelphij>Example 28. Form Windows Example </B 7124262685Sdelphij></P 7125262685Sdelphij><PRE 7126262685SdelphijCLASS="PROGRAMLISTING" 7127262685Sdelphij><SPAN 7128262685SdelphijCLASS="INLINEMEDIAOBJECT" 7129262685Sdelphij>#include <form.h> 7130166124Srafan 7131166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); 7132166124Srafan 7133166124Srafanint main() 7134166124Srafan{ 7135262685Sdelphij FIELD *field[3]; 7136262685Sdelphij FORM *my_form; 7137262685Sdelphij WINDOW *my_form_win; 7138262685Sdelphij int ch, rows, cols; 7139262685Sdelphij 7140262685Sdelphij /* Initialize curses */ 7141262685Sdelphij initscr(); 7142262685Sdelphij start_color(); 7143262685Sdelphij cbreak(); 7144262685Sdelphij noecho(); 7145262685Sdelphij keypad(stdscr, TRUE); 7146166124Srafan 7147262685Sdelphij /* Initialize few color pairs */ 7148262685Sdelphij init_pair(1, COLOR_RED, COLOR_BLACK); 7149166124Srafan 7150262685Sdelphij /* Initialize the fields */ 7151262685Sdelphij field[0] = new_field(1, 10, 6, 1, 0, 0); 7152262685Sdelphij field[1] = new_field(1, 10, 8, 1, 0, 0); 7153262685Sdelphij field[2] = NULL; 7154166124Srafan 7155262685Sdelphij /* Set field options */ 7156262685Sdelphij set_field_back(field[0], A_UNDERLINE); 7157262685Sdelphij field_opts_off(field[0], O_AUTOSKIP); /* Don't go to next field when this */ 7158262685Sdelphij /* Field is filled up */ 7159262685Sdelphij set_field_back(field[1], A_UNDERLINE); 7160262685Sdelphij field_opts_off(field[1], O_AUTOSKIP); 7161262685Sdelphij 7162262685Sdelphij /* Create the form and post it */ 7163262685Sdelphij my_form = new_form(field); 7164262685Sdelphij 7165262685Sdelphij /* Calculate the area required for the form */ 7166262685Sdelphij scale_form(my_form, &rows, &cols); 7167166124Srafan 7168262685Sdelphij /* Create the window to be associated with the form */ 7169166124Srafan my_form_win = newwin(rows + 4, cols + 4, 4, 4); 7170166124Srafan keypad(my_form_win, TRUE); 7171166124Srafan 7172262685Sdelphij /* Set main window and sub window */ 7173166124Srafan set_form_win(my_form, my_form_win); 7174166124Srafan set_form_sub(my_form, derwin(my_form_win, rows, cols, 2, 2)); 7175166124Srafan 7176262685Sdelphij /* Print a border around the main window and print a title */ 7177166124Srafan box(my_form_win, 0, 0); 7178262685Sdelphij print_in_middle(my_form_win, 1, 0, cols + 4, "My Form", COLOR_PAIR(1)); 7179262685Sdelphij 7180262685Sdelphij post_form(my_form); 7181262685Sdelphij wrefresh(my_form_win); 7182166124Srafan 7183262685Sdelphij mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields"); 7184262685Sdelphij refresh(); 7185166124Srafan 7186262685Sdelphij /* Loop through to get user requests */ 7187262685Sdelphij while((ch = wgetch(my_form_win)) != KEY_F(1)) 7188262685Sdelphij { switch(ch) 7189262685Sdelphij { case KEY_DOWN: 7190262685Sdelphij /* Go to next field */ 7191262685Sdelphij form_driver(my_form, REQ_NEXT_FIELD); 7192262685Sdelphij /* Go to the end of the present buffer */ 7193262685Sdelphij /* Leaves nicely at the last character */ 7194262685Sdelphij form_driver(my_form, REQ_END_LINE); 7195262685Sdelphij break; 7196262685Sdelphij case KEY_UP: 7197262685Sdelphij /* Go to previous field */ 7198262685Sdelphij form_driver(my_form, REQ_PREV_FIELD); 7199262685Sdelphij form_driver(my_form, REQ_END_LINE); 7200262685Sdelphij break; 7201262685Sdelphij default: 7202262685Sdelphij /* If this is a normal character, it gets */ 7203262685Sdelphij /* Printed */ 7204262685Sdelphij form_driver(my_form, ch); 7205262685Sdelphij break; 7206262685Sdelphij } 7207262685Sdelphij } 7208166124Srafan 7209262685Sdelphij /* Un post form and free the memory */ 7210262685Sdelphij unpost_form(my_form); 7211262685Sdelphij free_form(my_form); 7212262685Sdelphij free_field(field[0]); 7213262685Sdelphij free_field(field[1]); 7214166124Srafan 7215262685Sdelphij endwin(); 7216262685Sdelphij return 0; 7217166124Srafan} 7218166124Srafan 7219166124Srafanvoid print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) 7220262685Sdelphij{ int length, x, y; 7221262685Sdelphij float temp; 7222166124Srafan 7223262685Sdelphij if(win == NULL) 7224262685Sdelphij win = stdscr; 7225262685Sdelphij getyx(win, y, x); 7226262685Sdelphij if(startx != 0) 7227262685Sdelphij x = startx; 7228262685Sdelphij if(starty != 0) 7229262685Sdelphij y = starty; 7230262685Sdelphij if(width == 0) 7231262685Sdelphij width = 80; 7232166124Srafan 7233262685Sdelphij length = strlen(string); 7234262685Sdelphij temp = (width - length)/ 2; 7235262685Sdelphij x = startx + (int)temp; 7236262685Sdelphij wattron(win, color); 7237262685Sdelphij mvwprintw(win, y, x, "%s", string); 7238262685Sdelphij wattroff(win, color); 7239262685Sdelphij refresh(); 7240262685Sdelphij}</SPAN 7241262685Sdelphij></PRE 7242262685Sdelphij></DIV 7243262685Sdelphij></DIV 7244262685Sdelphij><DIV 7245262685SdelphijCLASS="SECT2" 7246262685Sdelphij><HR><H3 7247262685SdelphijCLASS="SECT2" 7248262685Sdelphij><A 7249262685SdelphijNAME="FILEDVALIDATE" 7250262685Sdelphij>18.5. Field Validation</A 7251262685Sdelphij></H3 7252262685Sdelphij><P 7253262685Sdelphij>By default, a field will accept any data input by the user. It is possible to 7254262685Sdelphijattach validation to the field. Then any attempt by the user to leave the field, 7255262685Sdelphijwhile it contains data that doesn't match the validation type will fail. Some 7256262685Sdelphijvalidation types also have a character-validity check for each time a character 7257262685Sdelphijis entered in the field.</P 7258262685Sdelphij><P 7259262685Sdelphij>Validation can be attached to a field with the following function. 7260262685Sdelphij<PRE 7261262685SdelphijCLASS="PROGRAMLISTING" 7262262685Sdelphij>int set_field_type(FIELD *field, /* field to alter */ 7263166124Srafan FIELDTYPE *ftype, /* type to associate */ 7264262685Sdelphij ...); /* additional arguments*/</PRE 7265262685Sdelphij> 7266166124SrafanOnce set, the validation type for a field can be queried with 7267262685Sdelphij<PRE 7268262685SdelphijCLASS="PROGRAMLISTING" 7269262685Sdelphij>FIELDTYPE *field_type(FIELD *field); /* field to query */</PRE 7270262685Sdelphij></P 7271262685Sdelphij><P 7272262685Sdelphij>The form driver validates the data in a field only when data is entered by the 7273262685Sdelphijend-user. Validation does not occur when </P 7274262685Sdelphij><P 7275262685Sdelphij></P 7276262685Sdelphij><UL 7277262685Sdelphij><LI 7278262685Sdelphij><P 7279262685Sdelphij>the application program changes the field value by calling set_field_buffer. </P 7280262685Sdelphij></LI 7281262685Sdelphij><LI 7282262685Sdelphij><P 7283262685Sdelphij>linked field values are changed indirectly -- by changing the field to which 7284262685Sdelphijthey are linked</P 7285262685Sdelphij></LI 7286262685Sdelphij></UL 7287262685Sdelphij><P 7288262685Sdelphij>The following are the pre-defined validation types. You can also specify custom 7289262685Sdelphijvalidation, though it's a bit tricky and cumbersome.</P 7290262685Sdelphij><H1 7291262685SdelphijCLASS="BRIDGEHEAD" 7292262685Sdelphij><A 7293262685SdelphijNAME="AEN1069" 7294262685Sdelphij></A 7295262685Sdelphij>TYPE_ALPHA</H1 7296262685Sdelphij><P 7297262685Sdelphij>This field type accepts alphabetic data; no blanks, no digits, no special 7298262685Sdelphijcharacters (this is checked at character-entry time). It is set up with: </P 7299262685Sdelphij><PRE 7300262685SdelphijCLASS="PROGRAMLISTING" 7301262685Sdelphij>int set_field_type(FIELD *field, /* field to alter */ 7302166124Srafan TYPE_ALPHA, /* type to associate */ 7303262685Sdelphij int width); /* maximum width of field */</PRE 7304262685Sdelphij><P 7305262685Sdelphij>The width argument sets a minimum width of data. The user has to enter at-least 7306262685Sdelphijwidth number of characters before he can leave the field. Typically 7307262685Sdelphijyou'll want to set this to the field width; if it's greater than the 7308262685Sdelphijfield width, the validation check will always fail. A minimum width 7309262685Sdelphijof zero makes field completion optional. </P 7310262685Sdelphij><H1 7311262685SdelphijCLASS="BRIDGEHEAD" 7312262685Sdelphij><A 7313262685SdelphijNAME="AEN1073" 7314262685Sdelphij></A 7315262685Sdelphij>TYPE_ALNUM</H1 7316262685Sdelphij><P 7317262685Sdelphij>This field type accepts alphabetic data and digits; no blanks, no special 7318262685Sdelphijcharacters (this is checked at character-entry time). It is set up with: </P 7319262685Sdelphij><PRE 7320262685SdelphijCLASS="PROGRAMLISTING" 7321262685Sdelphij>int set_field_type(FIELD *field, /* field to alter */ 7322166124Srafan TYPE_ALNUM, /* type to associate */ 7323262685Sdelphij int width); /* maximum width of field */</PRE 7324262685Sdelphij><P 7325262685Sdelphij>The width argument sets a minimum width of data. As with 7326262685SdelphijTYPE_ALPHA, typically you'll want to set this to the field width; if it's 7327262685Sdelphijgreater than the field width, the validation check will always fail. A 7328262685Sdelphijminimum width of zero makes field completion optional. </P 7329262685Sdelphij><H1 7330262685SdelphijCLASS="BRIDGEHEAD" 7331262685Sdelphij><A 7332262685SdelphijNAME="AEN1077" 7333262685Sdelphij></A 7334262685Sdelphij>TYPE_ENUM</H1 7335262685Sdelphij><P 7336262685Sdelphij>This type allows you to restrict a field's values to be among a specified 7337262685Sdelphijset of string values (for example, the two-letter postal codes for U.S. 7338262685Sdelphijstates). It is set up with: </P 7339262685Sdelphij><PRE 7340262685SdelphijCLASS="PROGRAMLISTING" 7341262685Sdelphij>int set_field_type(FIELD *field, /* field to alter */ 7342166124Srafan TYPE_ENUM, /* type to associate */ 7343166124Srafan char **valuelist; /* list of possible values */ 7344166124Srafan int checkcase; /* case-sensitive? */ 7345262685Sdelphij int checkunique); /* must specify uniquely? */</PRE 7346262685Sdelphij><P 7347262685Sdelphij>The valuelist parameter must point at a NULL-terminated list of 7348262685Sdelphijvalid strings. The checkcase argument, if true, makes comparison 7349262685Sdelphijwith the string case-sensitive. </P 7350262685Sdelphij><P 7351262685Sdelphij>When the user exits a TYPE_ENUM field, the validation procedure tries to 7352262685Sdelphijcomplete the data in the buffer to a valid entry. If a complete choice string 7353262685Sdelphijhas been entered, it is of course valid. But it is also possible to enter a 7354262685Sdelphijprefix of a valid string and have it completed for you. </P 7355262685Sdelphij><P 7356262685Sdelphij>By default, if you enter such a prefix and it matches more than one value 7357262685Sdelphijin the string list, the prefix will be completed to the first matching 7358262685Sdelphijvalue. But the checkunique argument, if true, requires prefix 7359262685Sdelphijmatches to be unique in order to be valid. </P 7360262685Sdelphij><P 7361262685Sdelphij>The REQ_NEXT_CHOICE and REQ_PREV_CHOICE input requests can be particularly 7362262685Sdelphijuseful with these fields. </P 7363262685Sdelphij><H1 7364262685SdelphijCLASS="BRIDGEHEAD" 7365262685Sdelphij><A 7366262685SdelphijNAME="AEN1084" 7367262685Sdelphij></A 7368262685Sdelphij>TYPE_INTEGER</H1 7369262685Sdelphij><P 7370262685Sdelphij>This field type accepts an integer. It is set up as follows: </P 7371262685Sdelphij><PRE 7372262685SdelphijCLASS="PROGRAMLISTING" 7373262685Sdelphij>int set_field_type(FIELD *field, /* field to alter */ 7374166124Srafan TYPE_INTEGER, /* type to associate */ 7375166124Srafan int padding, /* # places to zero-pad to */ 7376262685Sdelphij int vmin, int vmax); /* valid range */</PRE 7377262685Sdelphij><P 7378262685Sdelphij>Valid characters consist of an optional leading minus and digits. 7379262685SdelphijThe range check is performed on exit. If the range maximum is less 7380262685Sdelphijthan or equal to the minimum, the range is ignored. </P 7381262685Sdelphij><P 7382262685Sdelphij>If the value passes its range check, it is padded with as many leading 7383262685Sdelphijzero digits as necessary to meet the padding argument. </P 7384262685Sdelphij><P 7385262685Sdelphij>A TYPE_INTEGER value buffer can conveniently be interpreted with the C library 7386262685Sdelphijfunction atoi(3).</P 7387262685Sdelphij><H1 7388262685SdelphijCLASS="BRIDGEHEAD" 7389262685Sdelphij><A 7390262685SdelphijNAME="AEN1090" 7391262685Sdelphij></A 7392262685Sdelphij>TYPE_NUMERIC</H1 7393262685Sdelphij><P 7394262685Sdelphij>This field type accepts a decimal number. It is set up as follows: </P 7395262685Sdelphij><PRE 7396262685SdelphijCLASS="PROGRAMLISTING" 7397262685Sdelphij>int set_field_type(FIELD *field, /* field to alter */ 7398166124Srafan TYPE_NUMERIC, /* type to associate */ 7399166124Srafan int padding, /* # places of precision */ 7400262685Sdelphij int vmin, int vmax); /* valid range */</PRE 7401262685Sdelphij><P 7402262685Sdelphij>Valid characters consist of an optional leading minus and digits. possibly 7403262685Sdelphijincluding a decimal point. The range check is performed on exit. If the 7404262685Sdelphijrange maximum is less than or equal to the minimum, the range is 7405262685Sdelphijignored. </P 7406262685Sdelphij><P 7407262685Sdelphij>If the value passes its range check, it is padded with as many trailing 7408262685Sdelphijzero digits as necessary to meet the padding argument. </P 7409262685Sdelphij><P 7410262685Sdelphij>A TYPE_NUMERIC value buffer can conveniently be interpreted with the C library 7411262685Sdelphijfunction atof(3).</P 7412262685Sdelphij><H1 7413262685SdelphijCLASS="BRIDGEHEAD" 7414262685Sdelphij><A 7415262685SdelphijNAME="AEN1096" 7416262685Sdelphij></A 7417262685Sdelphij>TYPE_REGEXP</H1 7418262685Sdelphij><P 7419262685Sdelphij>This field type accepts data matching a regular expression. It is set up 7420262685Sdelphijas follows: </P 7421262685Sdelphij><PRE 7422262685SdelphijCLASS="PROGRAMLISTING" 7423262685Sdelphij>int set_field_type(FIELD *field, /* field to alter */ 7424166124Srafan TYPE_REGEXP, /* type to associate */ 7425262685Sdelphij char *regexp); /* expression to match */</PRE 7426262685Sdelphij><P 7427262685Sdelphij>The syntax for regular expressions is that of regcomp(3). 7428262685SdelphijThe check for regular-expression match is performed on exit.</P 7429262685Sdelphij></DIV 7430262685Sdelphij><DIV 7431262685SdelphijCLASS="SECT2" 7432262685Sdelphij><HR><H3 7433262685SdelphijCLASS="SECT2" 7434262685Sdelphij><A 7435262685SdelphijNAME="FORMDRIVER" 7436262685Sdelphij>18.6. Form Driver: The work horse of the forms system</A 7437262685Sdelphij></H3 7438262685Sdelphij><P 7439262685Sdelphij>As in the menu system, form_driver() plays a very important role in forms 7440262685Sdelphijsystem. All types of requests to forms system should be funneled through 7441262685Sdelphijform_driver().</P 7442262685Sdelphij><PRE 7443262685SdelphijCLASS="PROGRAMLISTING" 7444262685Sdelphij>int form_driver(FORM *form, /* form on which to operate */ 7445262685Sdelphij int request) /* form request code */</PRE 7446262685Sdelphij><P 7447262685Sdelphij>As you have seen some of the examples above, you have to be in a loop looking 7448262685Sdelphijfor user input and then decide whether it's a field data or a form request. The 7449262685Sdelphijform requests are then passed to form_driver() to do the work.</P 7450262685Sdelphij><P 7451262685Sdelphij>The requests roughly can be divided into following categories. Different 7452262685Sdelphijrequests and their usage is explained below:</P 7453262685Sdelphij><DIV 7454262685SdelphijCLASS="SECT3" 7455262685Sdelphij><HR><H4 7456262685SdelphijCLASS="SECT3" 7457262685Sdelphij><A 7458262685SdelphijNAME="PAGENAVREQ" 7459262685Sdelphij>18.6.1. Page Navigation Requests</A 7460262685Sdelphij></H4 7461262685Sdelphij><P 7462262685Sdelphij>These requests cause page-level moves through the form, triggering display of a 7463262685Sdelphijnew form screen. A form can be made of multiple pages. If you have a big form 7464262685Sdelphijwith lot of fields and logical sections, then you can divide the form into 7465262685Sdelphijpages. The function set_new_page() to set a new page at the field specified.</P 7466262685Sdelphij><PRE 7467262685SdelphijCLASS="PROGRAMLISTING" 7468262685Sdelphij>int set_new_page(FIELD *field,/* Field at which page break to be set or unset */ 7469262685Sdelphij bool new_page_flag); /* should be TRUE to put a break */</PRE 7470262685Sdelphij><P 7471262685Sdelphij>The following requests allow you to move to different pages</P 7472262685Sdelphij><P 7473262685Sdelphij></P 7474262685Sdelphij><UL 7475262685Sdelphij><LI 7476262685Sdelphij><P 7477262685Sdelphij><SPAN 7478262685SdelphijCLASS="emphasis" 7479262685Sdelphij><I 7480262685SdelphijCLASS="EMPHASIS" 7481262685Sdelphij>REQ_NEXT_PAGE</I 7482262685Sdelphij></SPAN 7483262685Sdelphij> Move to the next form page.</P 7484262685Sdelphij></LI 7485262685Sdelphij><LI 7486262685Sdelphij><P 7487262685Sdelphij><SPAN 7488262685SdelphijCLASS="emphasis" 7489262685Sdelphij><I 7490262685SdelphijCLASS="EMPHASIS" 7491262685Sdelphij>REQ_PREV_PAGE</I 7492262685Sdelphij></SPAN 7493262685Sdelphij> Move to the previous 7494262685Sdelphijform page.</P 7495262685Sdelphij></LI 7496262685Sdelphij><LI 7497262685Sdelphij><P 7498262685Sdelphij><SPAN 7499262685SdelphijCLASS="emphasis" 7500262685Sdelphij><I 7501262685SdelphijCLASS="EMPHASIS" 7502262685Sdelphij>REQ_FIRST_PAGE</I 7503262685Sdelphij></SPAN 7504262685Sdelphij> Move to the first form page.</P 7505262685Sdelphij></LI 7506262685Sdelphij><LI 7507262685Sdelphij><P 7508262685Sdelphij><SPAN 7509262685SdelphijCLASS="emphasis" 7510262685Sdelphij><I 7511262685SdelphijCLASS="EMPHASIS" 7512262685Sdelphij>REQ_LAST_PAGE</I 7513262685Sdelphij></SPAN 7514262685Sdelphij> Move to the last form page. </P 7515262685Sdelphij></LI 7516262685Sdelphij></UL 7517262685Sdelphij><P 7518262685Sdelphij>These requests treat the list as cyclic; that is, REQ_NEXT_PAGE from the 7519262685Sdelphijlast page goes to the first, and REQ_PREV_PAGE from the first page goes to 7520262685Sdelphijthe last.</P 7521262685Sdelphij></DIV 7522262685Sdelphij><DIV 7523262685SdelphijCLASS="SECT3" 7524262685Sdelphij><HR><H4 7525262685SdelphijCLASS="SECT3" 7526262685Sdelphij><A 7527262685SdelphijNAME="INTERFIELDNAVREQ" 7528262685Sdelphij>18.6.2. Inter-Field Navigation Requests</A 7529262685Sdelphij></H4 7530262685Sdelphij><P 7531262685Sdelphij>These requests handle navigation between fields on the same page.</P 7532262685Sdelphij><P 7533262685Sdelphij></P 7534262685Sdelphij><UL 7535262685Sdelphij><LI 7536262685Sdelphij><P 7537262685Sdelphij><SPAN 7538262685SdelphijCLASS="emphasis" 7539262685Sdelphij><I 7540262685SdelphijCLASS="EMPHASIS" 7541262685Sdelphij>REQ_NEXT_FIELD</I 7542262685Sdelphij></SPAN 7543262685Sdelphij> 7544262685Sdelphij Move to next field. </P 7545262685Sdelphij></LI 7546262685Sdelphij><LI 7547262685Sdelphij><P 7548262685Sdelphij><SPAN 7549262685SdelphijCLASS="emphasis" 7550262685Sdelphij><I 7551262685SdelphijCLASS="EMPHASIS" 7552262685Sdelphij>REQ_PREV_FIELD</I 7553262685Sdelphij></SPAN 7554262685Sdelphij> 7555262685Sdelphij Move to previous field. </P 7556262685Sdelphij></LI 7557262685Sdelphij><LI 7558262685Sdelphij><P 7559262685Sdelphij><SPAN 7560262685SdelphijCLASS="emphasis" 7561262685Sdelphij><I 7562262685SdelphijCLASS="EMPHASIS" 7563262685Sdelphij>REQ_FIRST_FIELD</I 7564262685Sdelphij></SPAN 7565262685Sdelphij> 7566262685Sdelphij Move to the first field. </P 7567262685Sdelphij></LI 7568262685Sdelphij><LI 7569262685Sdelphij><P 7570262685Sdelphij><SPAN 7571262685SdelphijCLASS="emphasis" 7572262685Sdelphij><I 7573262685SdelphijCLASS="EMPHASIS" 7574262685Sdelphij>REQ_LAST_FIELD</I 7575262685Sdelphij></SPAN 7576262685Sdelphij> 7577262685Sdelphij Move to the last field. </P 7578262685Sdelphij></LI 7579262685Sdelphij><LI 7580262685Sdelphij><P 7581262685Sdelphij><SPAN 7582262685SdelphijCLASS="emphasis" 7583262685Sdelphij><I 7584262685SdelphijCLASS="EMPHASIS" 7585262685Sdelphij>REQ_SNEXT_FIELD</I 7586262685Sdelphij></SPAN 7587262685Sdelphij> 7588262685Sdelphij Move to sorted next field. </P 7589262685Sdelphij></LI 7590262685Sdelphij><LI 7591262685Sdelphij><P 7592262685Sdelphij><SPAN 7593262685SdelphijCLASS="emphasis" 7594262685Sdelphij><I 7595262685SdelphijCLASS="EMPHASIS" 7596262685Sdelphij>REQ_SPREV_FIELD</I 7597262685Sdelphij></SPAN 7598262685Sdelphij> 7599262685Sdelphij Move to sorted previous field. </P 7600262685Sdelphij></LI 7601262685Sdelphij><LI 7602262685Sdelphij><P 7603262685Sdelphij><SPAN 7604262685SdelphijCLASS="emphasis" 7605262685Sdelphij><I 7606262685SdelphijCLASS="EMPHASIS" 7607262685Sdelphij>REQ_SFIRST_FIELD</I 7608262685Sdelphij></SPAN 7609262685Sdelphij> 7610262685Sdelphij Move to the sorted first field. </P 7611262685Sdelphij></LI 7612262685Sdelphij><LI 7613262685Sdelphij><P 7614262685Sdelphij><SPAN 7615262685SdelphijCLASS="emphasis" 7616262685Sdelphij><I 7617262685SdelphijCLASS="EMPHASIS" 7618262685Sdelphij>REQ_SLAST_FIELD</I 7619262685Sdelphij></SPAN 7620262685Sdelphij> 7621262685Sdelphij Move to the sorted last field. </P 7622262685Sdelphij></LI 7623262685Sdelphij><LI 7624262685Sdelphij><P 7625262685Sdelphij><SPAN 7626262685SdelphijCLASS="emphasis" 7627262685Sdelphij><I 7628262685SdelphijCLASS="EMPHASIS" 7629262685Sdelphij>REQ_LEFT_FIELD</I 7630262685Sdelphij></SPAN 7631262685Sdelphij> 7632262685Sdelphij Move left to field. </P 7633262685Sdelphij></LI 7634262685Sdelphij><LI 7635262685Sdelphij><P 7636262685Sdelphij><SPAN 7637262685SdelphijCLASS="emphasis" 7638262685Sdelphij><I 7639262685SdelphijCLASS="EMPHASIS" 7640262685Sdelphij>REQ_RIGHT_FIELD</I 7641262685Sdelphij></SPAN 7642262685Sdelphij> 7643262685Sdelphij Move right to field. </P 7644262685Sdelphij></LI 7645262685Sdelphij><LI 7646262685Sdelphij><P 7647262685Sdelphij><SPAN 7648262685SdelphijCLASS="emphasis" 7649262685Sdelphij><I 7650262685SdelphijCLASS="EMPHASIS" 7651262685Sdelphij>REQ_UP_FIELD</I 7652262685Sdelphij></SPAN 7653262685Sdelphij> 7654262685Sdelphij Move up to field. </P 7655262685Sdelphij></LI 7656262685Sdelphij><LI 7657262685Sdelphij><P 7658262685Sdelphij><SPAN 7659262685SdelphijCLASS="emphasis" 7660262685Sdelphij><I 7661262685SdelphijCLASS="EMPHASIS" 7662262685Sdelphij>REQ_DOWN_FIELD</I 7663262685Sdelphij></SPAN 7664262685Sdelphij> 7665262685Sdelphij Move down to field. </P 7666262685Sdelphij></LI 7667262685Sdelphij></UL 7668262685Sdelphij><P 7669262685Sdelphij>These requests treat the list of fields on a page as cyclic; that is, 7670262685SdelphijREQ_NEXT_FIELD from the last field goes to the first, and REQ_PREV_FIELD 7671262685Sdelphijfrom the first field goes to the last. The order of the fields for these 7672262685Sdelphij(and the REQ_FIRST_FIELD and REQ_LAST_FIELD requests) is simply the order of 7673262685Sdelphijthe field pointers in the form array (as set up by new_form() or 7674262685Sdelphijset_form_fields()</P 7675262685Sdelphij><P 7676262685Sdelphij>It is also possible to traverse the fields as if they had been sorted in 7677262685Sdelphijscreen-position order, so the sequence goes left-to-right and top-to-bottom. 7678262685SdelphijTo do this, use the second group of four sorted-movement requests.</P 7679262685Sdelphij><P 7680262685Sdelphij>Finally, it is possible to move between fields using visual directions up, 7681262685Sdelphijdown, right, and left. To accomplish this, use the third group of four 7682262685Sdelphijrequests. Note, however, that the position of a form for purposes of these 7683262685Sdelphijrequests is its upper-left corner.</P 7684262685Sdelphij><P 7685262685Sdelphij>For example, suppose you have a multi-line field B, and two single-line 7686262685Sdelphijfields A and C on the same line with B, with A to the left of B and C to the 7687262685Sdelphijright of B. A REQ_MOVE_RIGHT from A will go to B only if A, B, and C all 7688262685Sdelphijshare the same first line; otherwise it will skip over B to C.</P 7689262685Sdelphij></DIV 7690262685Sdelphij><DIV 7691262685SdelphijCLASS="SECT3" 7692262685Sdelphij><HR><H4 7693262685SdelphijCLASS="SECT3" 7694262685Sdelphij><A 7695262685SdelphijNAME="INTRAFIELDNAVREQ" 7696262685Sdelphij>18.6.3. Intra-Field Navigation Requests</A 7697262685Sdelphij></H4 7698262685Sdelphij><P 7699262685Sdelphij>These requests drive movement of the edit cursor within the currently 7700262685Sdelphijselected field.</P 7701262685Sdelphij><P 7702262685Sdelphij></P 7703262685Sdelphij><UL 7704262685Sdelphij><LI 7705262685Sdelphij><P 7706262685Sdelphij><SPAN 7707262685SdelphijCLASS="emphasis" 7708262685Sdelphij><I 7709262685SdelphijCLASS="EMPHASIS" 7710262685Sdelphij>REQ_NEXT_CHAR</I 7711262685Sdelphij></SPAN 7712262685Sdelphij> 7713262685Sdelphij Move to next character. </P 7714262685Sdelphij></LI 7715262685Sdelphij><LI 7716262685Sdelphij><P 7717262685Sdelphij><SPAN 7718262685SdelphijCLASS="emphasis" 7719262685Sdelphij><I 7720262685SdelphijCLASS="EMPHASIS" 7721262685Sdelphij>REQ_PREV_CHAR</I 7722262685Sdelphij></SPAN 7723262685Sdelphij> 7724262685Sdelphij Move to previous character. </P 7725262685Sdelphij></LI 7726262685Sdelphij><LI 7727262685Sdelphij><P 7728262685Sdelphij><SPAN 7729262685SdelphijCLASS="emphasis" 7730262685Sdelphij><I 7731262685SdelphijCLASS="EMPHASIS" 7732262685Sdelphij>REQ_NEXT_LINE</I 7733262685Sdelphij></SPAN 7734262685Sdelphij> 7735262685Sdelphij Move to next line. </P 7736262685Sdelphij></LI 7737262685Sdelphij><LI 7738262685Sdelphij><P 7739262685Sdelphij><SPAN 7740262685SdelphijCLASS="emphasis" 7741262685Sdelphij><I 7742262685SdelphijCLASS="EMPHASIS" 7743262685Sdelphij>REQ_PREV_LINE</I 7744262685Sdelphij></SPAN 7745262685Sdelphij> 7746262685Sdelphij Move to previous line. </P 7747262685Sdelphij></LI 7748262685Sdelphij><LI 7749262685Sdelphij><P 7750262685Sdelphij><SPAN 7751262685SdelphijCLASS="emphasis" 7752262685Sdelphij><I 7753262685SdelphijCLASS="EMPHASIS" 7754262685Sdelphij>REQ_NEXT_WORD</I 7755262685Sdelphij></SPAN 7756262685Sdelphij> 7757262685Sdelphij Move to next word. </P 7758262685Sdelphij></LI 7759262685Sdelphij><LI 7760262685Sdelphij><P 7761262685Sdelphij><SPAN 7762262685SdelphijCLASS="emphasis" 7763262685Sdelphij><I 7764262685SdelphijCLASS="EMPHASIS" 7765262685Sdelphij>REQ_PREV_WORD</I 7766262685Sdelphij></SPAN 7767262685Sdelphij> 7768262685Sdelphij Move to previous word. </P 7769262685Sdelphij></LI 7770262685Sdelphij><LI 7771262685Sdelphij><P 7772262685Sdelphij><SPAN 7773262685SdelphijCLASS="emphasis" 7774262685Sdelphij><I 7775262685SdelphijCLASS="EMPHASIS" 7776262685Sdelphij>REQ_BEG_FIELD</I 7777262685Sdelphij></SPAN 7778262685Sdelphij> 7779262685Sdelphij Move to beginning of field. </P 7780262685Sdelphij></LI 7781262685Sdelphij><LI 7782262685Sdelphij><P 7783262685Sdelphij><SPAN 7784262685SdelphijCLASS="emphasis" 7785262685Sdelphij><I 7786262685SdelphijCLASS="EMPHASIS" 7787262685Sdelphij>REQ_END_FIELD</I 7788262685Sdelphij></SPAN 7789262685Sdelphij> 7790262685Sdelphij Move to end of field. </P 7791262685Sdelphij></LI 7792262685Sdelphij><LI 7793262685Sdelphij><P 7794262685Sdelphij><SPAN 7795262685SdelphijCLASS="emphasis" 7796262685Sdelphij><I 7797262685SdelphijCLASS="EMPHASIS" 7798262685Sdelphij>REQ_BEG_LINE</I 7799262685Sdelphij></SPAN 7800262685Sdelphij> 7801262685Sdelphij Move to beginning of line. </P 7802262685Sdelphij></LI 7803262685Sdelphij><LI 7804262685Sdelphij><P 7805262685Sdelphij><SPAN 7806262685SdelphijCLASS="emphasis" 7807262685Sdelphij><I 7808262685SdelphijCLASS="EMPHASIS" 7809262685Sdelphij>REQ_END_LINE</I 7810262685Sdelphij></SPAN 7811262685Sdelphij> 7812262685Sdelphij Move to end of line. </P 7813262685Sdelphij></LI 7814262685Sdelphij><LI 7815262685Sdelphij><P 7816262685Sdelphij><SPAN 7817262685SdelphijCLASS="emphasis" 7818262685Sdelphij><I 7819262685SdelphijCLASS="EMPHASIS" 7820262685Sdelphij>REQ_LEFT_CHAR</I 7821262685Sdelphij></SPAN 7822262685Sdelphij> 7823262685Sdelphij Move left in field. </P 7824262685Sdelphij></LI 7825262685Sdelphij><LI 7826262685Sdelphij><P 7827262685Sdelphij><SPAN 7828262685SdelphijCLASS="emphasis" 7829262685Sdelphij><I 7830262685SdelphijCLASS="EMPHASIS" 7831262685Sdelphij>REQ_RIGHT_CHAR</I 7832262685Sdelphij></SPAN 7833262685Sdelphij> 7834262685Sdelphij Move right in field. </P 7835262685Sdelphij></LI 7836262685Sdelphij><LI 7837262685Sdelphij><P 7838262685Sdelphij><SPAN 7839262685SdelphijCLASS="emphasis" 7840262685Sdelphij><I 7841262685SdelphijCLASS="EMPHASIS" 7842262685Sdelphij>REQ_UP_CHAR</I 7843262685Sdelphij></SPAN 7844262685Sdelphij> 7845262685Sdelphij Move up in field. </P 7846262685Sdelphij></LI 7847262685Sdelphij><LI 7848262685Sdelphij><P 7849262685Sdelphij><SPAN 7850262685SdelphijCLASS="emphasis" 7851262685Sdelphij><I 7852262685SdelphijCLASS="EMPHASIS" 7853262685Sdelphij>REQ_DOWN_CHAR</I 7854262685Sdelphij></SPAN 7855262685Sdelphij> 7856262685Sdelphij Move down in field. </P 7857262685Sdelphij></LI 7858262685Sdelphij></UL 7859262685Sdelphij><P 7860262685Sdelphij>Each word is separated from the previous and next characters by whitespace. 7861262685SdelphijThe commands to move to beginning and end of line or field look for the 7862262685Sdelphijfirst or last non-pad character in their ranges.</P 7863262685Sdelphij></DIV 7864262685Sdelphij><DIV 7865262685SdelphijCLASS="SECT3" 7866262685Sdelphij><HR><H4 7867262685SdelphijCLASS="SECT3" 7868262685Sdelphij><A 7869262685SdelphijNAME="SCROLLREQ" 7870262685Sdelphij>18.6.4. Scrolling Requests</A 7871262685Sdelphij></H4 7872262685Sdelphij><P 7873262685Sdelphij>Fields that are dynamic and have grown and fields explicitly created with 7874262685Sdelphijoffscreen rows are scrollable. One-line fields scroll horizontally; 7875262685Sdelphijmulti-line fields scroll vertically. Most scrolling is triggered by editing 7876262685Sdelphijand intra-field movement (the library scrolls the field to keep the cursor 7877262685Sdelphijvisible). It is possible to explicitly request scrolling with the following 7878262685Sdelphijrequests:</P 7879262685Sdelphij><P 7880262685Sdelphij></P 7881262685Sdelphij><UL 7882262685Sdelphij><LI 7883262685Sdelphij><P 7884262685Sdelphij><SPAN 7885262685SdelphijCLASS="emphasis" 7886262685Sdelphij><I 7887262685SdelphijCLASS="EMPHASIS" 7888262685Sdelphij>REQ_SCR_FLINE</I 7889262685Sdelphij></SPAN 7890262685Sdelphij> 7891262685Sdelphij Scroll vertically forward a line. </P 7892262685Sdelphij></LI 7893262685Sdelphij><LI 7894262685Sdelphij><P 7895262685Sdelphij><SPAN 7896262685SdelphijCLASS="emphasis" 7897262685Sdelphij><I 7898262685SdelphijCLASS="EMPHASIS" 7899262685Sdelphij>REQ_SCR_BLINE</I 7900262685Sdelphij></SPAN 7901262685Sdelphij> 7902262685Sdelphij Scroll vertically backward a line. </P 7903262685Sdelphij></LI 7904262685Sdelphij><LI 7905262685Sdelphij><P 7906262685Sdelphij><SPAN 7907262685SdelphijCLASS="emphasis" 7908262685Sdelphij><I 7909262685SdelphijCLASS="EMPHASIS" 7910262685Sdelphij>REQ_SCR_FPAGE</I 7911262685Sdelphij></SPAN 7912262685Sdelphij> 7913262685Sdelphij Scroll vertically forward a page. </P 7914262685Sdelphij></LI 7915262685Sdelphij><LI 7916262685Sdelphij><P 7917262685Sdelphij><SPAN 7918262685SdelphijCLASS="emphasis" 7919262685Sdelphij><I 7920262685SdelphijCLASS="EMPHASIS" 7921262685Sdelphij>REQ_SCR_BPAGE</I 7922262685Sdelphij></SPAN 7923262685Sdelphij> 7924262685Sdelphij Scroll vertically backward a page. </P 7925262685Sdelphij></LI 7926262685Sdelphij><LI 7927262685Sdelphij><P 7928262685Sdelphij><SPAN 7929262685SdelphijCLASS="emphasis" 7930262685Sdelphij><I 7931262685SdelphijCLASS="EMPHASIS" 7932262685Sdelphij>REQ_SCR_FHPAGE</I 7933262685Sdelphij></SPAN 7934262685Sdelphij> 7935262685Sdelphij Scroll vertically forward half a page. </P 7936262685Sdelphij></LI 7937262685Sdelphij><LI 7938262685Sdelphij><P 7939262685Sdelphij><SPAN 7940262685SdelphijCLASS="emphasis" 7941262685Sdelphij><I 7942262685SdelphijCLASS="EMPHASIS" 7943262685Sdelphij>REQ_SCR_BHPAGE</I 7944262685Sdelphij></SPAN 7945262685Sdelphij> 7946262685Sdelphij Scroll vertically backward half a page. </P 7947262685Sdelphij></LI 7948262685Sdelphij><LI 7949262685Sdelphij><P 7950262685Sdelphij><SPAN 7951262685SdelphijCLASS="emphasis" 7952262685Sdelphij><I 7953262685SdelphijCLASS="EMPHASIS" 7954262685Sdelphij>REQ_SCR_FCHAR</I 7955262685Sdelphij></SPAN 7956262685Sdelphij> 7957262685Sdelphij Scroll horizontally forward a character. </P 7958262685Sdelphij></LI 7959262685Sdelphij><LI 7960262685Sdelphij><P 7961262685Sdelphij><SPAN 7962262685SdelphijCLASS="emphasis" 7963262685Sdelphij><I 7964262685SdelphijCLASS="EMPHASIS" 7965262685Sdelphij>REQ_SCR_BCHAR</I 7966262685Sdelphij></SPAN 7967262685Sdelphij> 7968262685Sdelphij Scroll horizontally backward a character. </P 7969262685Sdelphij></LI 7970262685Sdelphij><LI 7971262685Sdelphij><P 7972262685Sdelphij><SPAN 7973262685SdelphijCLASS="emphasis" 7974262685Sdelphij><I 7975262685SdelphijCLASS="EMPHASIS" 7976262685Sdelphij>REQ_SCR_HFLINE</I 7977262685Sdelphij></SPAN 7978262685Sdelphij> 7979262685Sdelphij Scroll horizontally one field width forward. </P 7980262685Sdelphij></LI 7981262685Sdelphij><LI 7982262685Sdelphij><P 7983262685Sdelphij><SPAN 7984262685SdelphijCLASS="emphasis" 7985262685Sdelphij><I 7986262685SdelphijCLASS="EMPHASIS" 7987262685Sdelphij>REQ_SCR_HBLINE</I 7988262685Sdelphij></SPAN 7989262685Sdelphij> 7990262685Sdelphij Scroll horizontally one field width backward. </P 7991262685Sdelphij></LI 7992262685Sdelphij><LI 7993262685Sdelphij><P 7994262685Sdelphij><SPAN 7995262685SdelphijCLASS="emphasis" 7996262685Sdelphij><I 7997262685SdelphijCLASS="EMPHASIS" 7998262685Sdelphij>REQ_SCR_HFHALF</I 7999262685Sdelphij></SPAN 8000262685Sdelphij> 8001262685Sdelphij Scroll horizontally one half field width forward. </P 8002262685Sdelphij></LI 8003262685Sdelphij><LI 8004262685Sdelphij><P 8005262685Sdelphij><SPAN 8006262685SdelphijCLASS="emphasis" 8007262685Sdelphij><I 8008262685SdelphijCLASS="EMPHASIS" 8009262685Sdelphij>REQ_SCR_HBHALF</I 8010262685Sdelphij></SPAN 8011262685Sdelphij> 8012262685Sdelphij Scroll horizontally one half field width backward. </P 8013262685Sdelphij></LI 8014262685Sdelphij></UL 8015262685Sdelphij><P 8016262685Sdelphij>For scrolling purposes, a page of a field is the height of its visible part.</P 8017262685Sdelphij></DIV 8018262685Sdelphij><DIV 8019262685SdelphijCLASS="SECT3" 8020262685Sdelphij><HR><H4 8021262685SdelphijCLASS="SECT3" 8022262685Sdelphij><A 8023262685SdelphijNAME="EDITREQ" 8024262685Sdelphij>18.6.5. Editing Requests</A 8025262685Sdelphij></H4 8026262685Sdelphij><P 8027262685Sdelphij>When you pass the forms driver an ASCII character, it is treated as a 8028262685Sdelphijrequest to add the character to the field's data buffer. Whether this is an 8029262685Sdelphijinsertion or a replacement depends on the field's edit mode (insertion is 8030262685Sdelphijthe default.</P 8031262685Sdelphij><P 8032262685Sdelphij>The following requests support editing the field and changing the edit mode:</P 8033262685Sdelphij><P 8034262685Sdelphij></P 8035262685Sdelphij><UL 8036262685Sdelphij><LI 8037262685Sdelphij><P 8038262685Sdelphij><SPAN 8039262685SdelphijCLASS="emphasis" 8040262685Sdelphij><I 8041262685SdelphijCLASS="EMPHASIS" 8042262685Sdelphij>REQ_INS_MODE</I 8043262685Sdelphij></SPAN 8044262685Sdelphij> 8045262685Sdelphij Set insertion mode. </P 8046262685Sdelphij></LI 8047262685Sdelphij><LI 8048262685Sdelphij><P 8049262685Sdelphij><SPAN 8050262685SdelphijCLASS="emphasis" 8051262685Sdelphij><I 8052262685SdelphijCLASS="EMPHASIS" 8053262685Sdelphij>REQ_OVL_MODE</I 8054262685Sdelphij></SPAN 8055262685Sdelphij> 8056262685Sdelphij Set overlay mode. </P 8057262685Sdelphij></LI 8058262685Sdelphij><LI 8059262685Sdelphij><P 8060262685Sdelphij><SPAN 8061262685SdelphijCLASS="emphasis" 8062262685Sdelphij><I 8063262685SdelphijCLASS="EMPHASIS" 8064262685Sdelphij>REQ_NEW_LINE</I 8065262685Sdelphij></SPAN 8066262685Sdelphij> 8067262685Sdelphij New line request (see below for explanation). </P 8068262685Sdelphij></LI 8069262685Sdelphij><LI 8070262685Sdelphij><P 8071262685Sdelphij><SPAN 8072262685SdelphijCLASS="emphasis" 8073262685Sdelphij><I 8074262685SdelphijCLASS="EMPHASIS" 8075262685Sdelphij>REQ_INS_CHAR</I 8076262685Sdelphij></SPAN 8077262685Sdelphij> 8078262685Sdelphij Insert space at character location. </P 8079262685Sdelphij></LI 8080262685Sdelphij><LI 8081262685Sdelphij><P 8082262685Sdelphij><SPAN 8083262685SdelphijCLASS="emphasis" 8084262685Sdelphij><I 8085262685SdelphijCLASS="EMPHASIS" 8086262685Sdelphij>REQ_INS_LINE</I 8087262685Sdelphij></SPAN 8088262685Sdelphij> 8089262685Sdelphij Insert blank line at character location. </P 8090262685Sdelphij></LI 8091262685Sdelphij><LI 8092262685Sdelphij><P 8093262685Sdelphij><SPAN 8094262685SdelphijCLASS="emphasis" 8095262685Sdelphij><I 8096262685SdelphijCLASS="EMPHASIS" 8097262685Sdelphij>REQ_DEL_CHAR</I 8098262685Sdelphij></SPAN 8099262685Sdelphij> 8100262685Sdelphij Delete character at cursor. </P 8101262685Sdelphij></LI 8102262685Sdelphij><LI 8103262685Sdelphij><P 8104262685Sdelphij><SPAN 8105262685SdelphijCLASS="emphasis" 8106262685Sdelphij><I 8107262685SdelphijCLASS="EMPHASIS" 8108262685Sdelphij>REQ_DEL_PREV</I 8109262685Sdelphij></SPAN 8110262685Sdelphij> 8111262685Sdelphij Delete previous word at cursor. </P 8112262685Sdelphij></LI 8113262685Sdelphij><LI 8114262685Sdelphij><P 8115262685Sdelphij><SPAN 8116262685SdelphijCLASS="emphasis" 8117262685Sdelphij><I 8118262685SdelphijCLASS="EMPHASIS" 8119262685Sdelphij>REQ_DEL_LINE</I 8120262685Sdelphij></SPAN 8121262685Sdelphij> 8122262685Sdelphij Delete line at cursor. </P 8123262685Sdelphij></LI 8124262685Sdelphij><LI 8125262685Sdelphij><P 8126262685Sdelphij><SPAN 8127262685SdelphijCLASS="emphasis" 8128262685Sdelphij><I 8129262685SdelphijCLASS="EMPHASIS" 8130262685Sdelphij>REQ_DEL_WORD</I 8131262685Sdelphij></SPAN 8132262685Sdelphij> 8133262685Sdelphij Delete word at cursor. </P 8134262685Sdelphij></LI 8135262685Sdelphij><LI 8136262685Sdelphij><P 8137262685Sdelphij><SPAN 8138262685SdelphijCLASS="emphasis" 8139262685Sdelphij><I 8140262685SdelphijCLASS="EMPHASIS" 8141262685Sdelphij>REQ_CLR_EOL</I 8142262685Sdelphij></SPAN 8143262685Sdelphij> 8144262685Sdelphij Clear to end of line. </P 8145262685Sdelphij></LI 8146262685Sdelphij><LI 8147262685Sdelphij><P 8148262685Sdelphij><SPAN 8149262685SdelphijCLASS="emphasis" 8150262685Sdelphij><I 8151262685SdelphijCLASS="EMPHASIS" 8152262685Sdelphij>REQ_CLR_EOF</I 8153262685Sdelphij></SPAN 8154262685Sdelphij> 8155262685Sdelphij Clear to end of field. </P 8156262685Sdelphij></LI 8157262685Sdelphij><LI 8158262685Sdelphij><P 8159262685Sdelphij><SPAN 8160262685SdelphijCLASS="emphasis" 8161262685Sdelphij><I 8162262685SdelphijCLASS="EMPHASIS" 8163262685Sdelphij>REQ_CLR_FIELD</I 8164262685Sdelphij></SPAN 8165262685Sdelphij> 8166262685Sdelphij Clear entire field. </P 8167262685Sdelphij></LI 8168262685Sdelphij></UL 8169262685Sdelphij><P 8170262685Sdelphij>The behavior of the REQ_NEW_LINE and REQ_DEL_PREV requests is complicated 8171262685Sdelphijand partly controlled by a pair of forms options. The special cases are 8172262685Sdelphijtriggered when the cursor is at the beginning of a field, or on the last 8173262685Sdelphijline of the field.</P 8174262685Sdelphij><P 8175262685Sdelphij>First, we consider REQ_NEW_LINE:</P 8176262685Sdelphij><P 8177262685Sdelphij>The normal behavior of REQ_NEW_LINE in insert mode is to break the current 8178262685Sdelphijline at the position of the edit cursor, inserting the portion of the 8179262685Sdelphijcurrent line after the cursor as a new line following the current and moving 8180262685Sdelphijthe cursor to the beginning of that new line (you may think of this as 8181262685Sdelphijinserting a newline in the field buffer).</P 8182262685Sdelphij><P 8183262685Sdelphij>The normal behavior of REQ_NEW_LINE in overlay mode is to clear the current 8184262685Sdelphijline from the position of the edit cursor to end of line. The cursor is then 8185262685Sdelphijmoved to the beginning of the next line.</P 8186262685Sdelphij><P 8187262685Sdelphij>However, REQ_NEW_LINE at the beginning of a field, or on the last line of a 8188262685Sdelphijfield, instead does a REQ_NEXT_FIELD. O_NL_OVERLOAD option is off, this 8189262685Sdelphijspecial action is disabled.</P 8190262685Sdelphij><P 8191262685Sdelphij>Now, let us consider REQ_DEL_PREV:</P 8192262685Sdelphij><P 8193262685Sdelphij>The normal behavior of REQ_DEL_PREV is to delete the previous character. If 8194262685Sdelphijinsert mode is on, and the cursor is at the start of a line, and the text on 8195262685Sdelphijthat line will fit on the previous one, it instead appends the contents of 8196262685Sdelphijthe current line to the previous one and deletes the current line (you may 8197262685Sdelphijthink of this as deleting a newline from the field buffer).</P 8198262685Sdelphij><P 8199262685Sdelphij>However, REQ_DEL_PREV at the beginning of a field is instead treated as a 8200262685SdelphijREQ_PREV_FIELD.</P 8201262685Sdelphij><P 8202262685Sdelphij>If the O_BS_OVERLOAD option is off, this special action is disabled and the 8203262685Sdelphijforms driver just returns E_REQUEST_DENIED.</P 8204262685Sdelphij></DIV 8205262685Sdelphij><DIV 8206262685SdelphijCLASS="SECT3" 8207262685Sdelphij><HR><H4 8208262685SdelphijCLASS="SECT3" 8209262685Sdelphij><A 8210262685SdelphijNAME="ORDERREQ" 8211262685Sdelphij>18.6.6. Order Requests</A 8212262685Sdelphij></H4 8213262685Sdelphij><P 8214262685Sdelphij>If the type of your field is ordered, and has associated functions for 8215262685Sdelphijgetting the next and previous values of the type from a given value, there 8216262685Sdelphijare requests that can fetch that value into the field buffer:</P 8217262685Sdelphij><P 8218262685Sdelphij></P 8219262685Sdelphij><UL 8220262685Sdelphij><LI 8221262685Sdelphij><P 8222262685Sdelphij><SPAN 8223262685SdelphijCLASS="emphasis" 8224262685Sdelphij><I 8225262685SdelphijCLASS="EMPHASIS" 8226262685Sdelphij>REQ_NEXT_CHOICE</I 8227262685Sdelphij></SPAN 8228262685Sdelphij> 8229262685Sdelphij Place the successor value of the current value in the buffer. 8230262685Sdelphij </P 8231262685Sdelphij></LI 8232262685Sdelphij><LI 8233262685Sdelphij><P 8234262685Sdelphij><SPAN 8235262685SdelphijCLASS="emphasis" 8236262685Sdelphij><I 8237262685SdelphijCLASS="EMPHASIS" 8238262685Sdelphij>REQ_PREV_CHOICE</I 8239262685Sdelphij></SPAN 8240262685Sdelphij> 8241262685Sdelphij Place the predecessor value of the current value in the buffer. 8242262685Sdelphij </P 8243262685Sdelphij></LI 8244262685Sdelphij></UL 8245262685Sdelphij><P 8246262685Sdelphij>Of the built-in field types, only TYPE_ENUM has built-in successor and 8247262685Sdelphijpredecessor functions. When you define a field type of your own (see Custom 8248262685SdelphijValidation Types), you can associate our own ordering functions.</P 8249262685Sdelphij></DIV 8250262685Sdelphij><DIV 8251262685SdelphijCLASS="SECT3" 8252262685Sdelphij><HR><H4 8253262685SdelphijCLASS="SECT3" 8254262685Sdelphij><A 8255262685SdelphijNAME="APPLICCOMMANDS" 8256262685Sdelphij>18.6.7. Application Commands</A 8257262685Sdelphij></H4 8258262685Sdelphij><P 8259262685Sdelphij>Form requests are represented as integers above the curses value greater than 8260262685SdelphijKEY_MAX and less than or equal to the constant MAX_COMMAND. A value within this 8261262685Sdelphijrange gets ignored by form_driver(). So this can be used for any purpose by the 8262262685Sdelphijapplication. It can be treated as an application specific action and take 8263262685Sdelphijcorresponding action.</P 8264262685Sdelphij></DIV 8265262685Sdelphij></DIV 8266262685Sdelphij></DIV 8267262685Sdelphij><DIV 8268262685SdelphijCLASS="SECT1" 8269262685Sdelphij><HR><H2 8270262685SdelphijCLASS="SECT1" 8271262685Sdelphij><A 8272262685SdelphijNAME="TOOLS" 8273262685Sdelphij>19. Tools and Widget Libraries</A 8274262685Sdelphij></H2 8275262685Sdelphij><P 8276262685Sdelphij> 8277262685SdelphijNow that you have seen the capabilities of ncurses and its sister libraries, you 8278262685Sdelphijare rolling your sleeves up and gearing for a project that heavily manipulates 8279262685Sdelphijscreen. But wait.. It can be pretty difficult to write and maintain complex GUI 8280262685Sdelphijwidgets in plain ncurses or even with the additional libraries. There are some 8281262685Sdelphijready-to-use tools and widget libraries that can be used instead of writing your 8282262685Sdelphijown widgets. You can use some of them, get ideas from the code, or even extend 8283262685Sdelphijthem.</P 8284262685Sdelphij><DIV 8285262685SdelphijCLASS="SECT2" 8286262685Sdelphij><HR><H3 8287262685SdelphijCLASS="SECT2" 8288262685Sdelphij><A 8289262685SdelphijNAME="CDK" 8290262685Sdelphij>19.1. CDK (Curses Development Kit)</A 8291262685Sdelphij></H3 8292262685Sdelphij><P 8293262685Sdelphij>In the author's words </P 8294262685Sdelphij><P 8295262685Sdelphij><SPAN 8296262685SdelphijCLASS="emphasis" 8297262685Sdelphij><I 8298262685SdelphijCLASS="EMPHASIS" 8299262685Sdelphij> 8300262685SdelphijCDK stands for 'Curses Development Kit' and it currently contains 21 ready 8301262685Sdelphijto use widgets which facilitate the speedy development of full screen 8302262685Sdelphijcurses programs. </I 8303262685Sdelphij></SPAN 8304262685Sdelphij></P 8305262685Sdelphij><P 8306262685Sdelphij>The kit provides some useful widgets, which can be used in your programs 8307262685Sdelphijdirectly. It's pretty well written and the documentation is very good. The 8308262685Sdelphijexamples in the examples directory can be a good place to start for beginners. 8309262685SdelphijThe CDK can be downloaded from <A 8310262685SdelphijHREF="http://invisible-island.net/cdk/" 8311262685SdelphijTARGET="_top" 8312262685Sdelphij>http://invisible-island.net/cdk/</A 8313262685Sdelphij> 8314262685Sdelphij. Follow the instructions in 8315262685SdelphijREADME file to install it.</P 8316262685Sdelphij><DIV 8317262685SdelphijCLASS="SECT3" 8318262685Sdelphij><HR><H4 8319262685SdelphijCLASS="SECT3" 8320262685Sdelphij><A 8321262685SdelphijNAME="WIDGETLIST" 8322262685Sdelphij>19.1.1. Widget List</A 8323262685Sdelphij></H4 8324262685Sdelphij><P 8325262685Sdelphij>The following is the list of widgets provided with cdk and their description.</P 8326262685Sdelphij><PRE 8327262685SdelphijCLASS="PROGRAMLISTING" 8328262685Sdelphij>Widget Type Quick Description 8329166124Srafan=========================================================================== 8330166124SrafanAlphalist Allows a user to select from a list of words, with 8331166124Srafan the ability to narrow the search list by typing in a 8332166124Srafan few characters of the desired word. 8333166124SrafanButtonbox This creates a multiple button widget. 8334166124SrafanCalendar Creates a little simple calendar widget. 8335166124SrafanDialog Prompts the user with a message, and the user 8336166124Srafan can pick an answer from the buttons provided. 8337166124SrafanEntry Allows the user to enter various types of information. 8338166124SrafanFile Selector A file selector built from Cdk base widgets. This 8339166124Srafan example shows how to create more complicated widgets 8340166124Srafan using the Cdk widget library. 8341166124SrafanGraph Draws a graph. 8342166124SrafanHistogram Draws a histogram. 8343166124SrafanItem List Creates a pop up field which allows the user to select 8344166124Srafan one of several choices in a small field. Very useful 8345166124Srafan for things like days of the week or month names. 8346166124SrafanLabel Displays messages in a pop up box, or the label can be 8347166124Srafan considered part of the screen. 8348166124SrafanMarquee Displays a message in a scrolling marquee. 8349166124SrafanMatrix Creates a complex matrix with lots of options. 8350166124SrafanMenu Creates a pull-down menu interface. 8351166124SrafanMultiple Line Entry A multiple line entry field. Very useful 8352166124Srafan for long fields. (like a description 8353166124Srafan field) 8354166124SrafanRadio List Creates a radio button list. 8355166124SrafanScale Creates a numeric scale. Used for allowing a user to 8356166124Srafan pick a numeric value and restrict them to a range of 8357166124Srafan values. 8358166124SrafanScrolling List Creates a scrolling list/menu list. 8359166124SrafanScrolling Window Creates a scrolling log file viewer. Can add 8360166124Srafan information into the window while its running. 8361166124Srafan A good widget for displaying the progress of 8362166124Srafan something. (akin to a console window) 8363166124SrafanSelection List Creates a multiple option selection list. 8364166124SrafanSlider Akin to the scale widget, this widget provides a 8365166124Srafan visual slide bar to represent the numeric value. 8366166124SrafanTemplate Creates a entry field with character sensitive 8367166124Srafan positions. Used for pre-formatted fields like 8368166124Srafan dates and phone numbers. 8369166124SrafanViewer This is a file/information viewer. Very useful 8370166124Srafan when you need to display loads of information. 8371262685Sdelphij===========================================================================</PRE 8372262685Sdelphij><P 8373262685Sdelphij>A few of the widgets are modified by Thomas Dickey in recent versions.</P 8374262685Sdelphij></DIV 8375262685Sdelphij><DIV 8376262685SdelphijCLASS="SECT3" 8377262685Sdelphij><HR><H4 8378262685SdelphijCLASS="SECT3" 8379262685Sdelphij><A 8380262685SdelphijNAME="CDKATTRACT" 8381262685Sdelphij>19.1.2. Some Attractive Features</A 8382262685Sdelphij></H4 8383262685Sdelphij><P 8384262685Sdelphij>Apart from making our life easier with readily usable widgets, cdk solves one 8385262685Sdelphijfrustrating problem with printing multi colored strings, justified strings 8386262685Sdelphijelegantly. Special formatting tags can be embedded in the strings which are 8387262685Sdelphijpassed to CDK functions. For Example</P 8388262685Sdelphij><P 8389262685Sdelphij>If the string</P 8390262685Sdelphij><PRE 8391262685SdelphijCLASS="PROGRAMLISTING" 8392262685Sdelphij>"</B/1>This line should have a yellow foreground and a blue 8393262685Sdelphijbackground.<!1>"</PRE 8394262685Sdelphij><P 8395262685Sdelphij>given as a parameter to newCDKLabel(), it prints the line with yellow foreground 8396262685Sdelphijand blue background. There are other tags available for justifying string, 8397262685Sdelphijembedding special drawing characters etc.. Please refer to the man page 8398262685Sdelphijcdk_display(3X) for details. The man page explains the usage with nice examples.</P 8399262685Sdelphij></DIV 8400262685Sdelphij><DIV 8401262685SdelphijCLASS="SECT3" 8402262685Sdelphij><HR><H4 8403262685SdelphijCLASS="SECT3" 8404262685Sdelphij><A 8405262685SdelphijNAME="CDKCONCLUSION" 8406262685Sdelphij>19.1.3. Conclusion</A 8407262685Sdelphij></H4 8408262685Sdelphij><P 8409262685Sdelphij>All in all, CDK is a well-written package of widgets, which if used properly can 8410262685Sdelphijform a strong frame work for developing complex GUI.</P 8411262685Sdelphij></DIV 8412262685Sdelphij></DIV 8413262685Sdelphij><DIV 8414262685SdelphijCLASS="SECT2" 8415262685Sdelphij><HR><H3 8416262685SdelphijCLASS="SECT2" 8417262685Sdelphij><A 8418262685SdelphijNAME="DIALOG" 8419262685Sdelphij>19.2. The dialog</A 8420262685Sdelphij></H3 8421262685Sdelphij><P 8422262685Sdelphij>Long long ago, in September 1994, when few people knew linux, Jeff Tranter wrote 8423262685Sdelphijan <A 8424262685SdelphijHREF="http://www2.linuxjournal.com/lj-issues/issue5/2807.html" 8425262685SdelphijTARGET="_top" 8426262685Sdelphij>article</A 8427262685Sdelphij> on dialog in Linux Journal. He starts the article with these words..</P 8428262685Sdelphij><P 8429262685Sdelphij><SPAN 8430262685SdelphijCLASS="emphasis" 8431262685Sdelphij><I 8432262685SdelphijCLASS="EMPHASIS" 8433262685Sdelphij>Linux is based on the Unix operating system, but also features a number of 8434262685Sdelphijunique and useful kernel features and application programs that often go beyond 8435262685Sdelphijwhat is available under Unix. One little-known gem is "dialog", a utility for 8436262685Sdelphijcreating professional-looking dialog boxes from within shell scripts. This 8437262685Sdelphijarticle presents a tutorial introduction to the dialog utility, and shows 8438262685Sdelphijexamples of how and where it can be used</I 8439262685Sdelphij></SPAN 8440262685Sdelphij></P 8441262685Sdelphij><P 8442262685Sdelphij> 8443262685SdelphijAs he explains, dialog is a real gem in making professional-looking dialog boxes 8444262685Sdelphijwith ease. It creates a variety of dialog boxes, menus, check lists etc.. It is 8445262685Sdelphijusually installed by default. If not, you can download it from <A 8446262685SdelphijHREF="http://invisible-island.net/dialog/" 8447262685SdelphijTARGET="_top" 8448262685Sdelphij>Thomas Dickey</A 8449262685Sdelphij>'s site. </P 8450262685Sdelphij><P 8451262685Sdelphij>The above-mentioned article gives a very good overview of its uses and 8452262685Sdelphijcapabilites. The man page has more details. It can be used in variety of 8453262685Sdelphijsituations. One good example is building of linux kernel in text mode. Linux 8454262685Sdelphijkernel uses a modified version of dialog tailored for its needs. </P 8455262685Sdelphij><P 8456262685Sdelphij>dialog was initially designed to be used with shell scripts. If you want to use 8457262685Sdelphijits functionality in a c program, then you can use libdialog. The documentation 8458262685Sdelphijregarding this is sparse. Definitive reference is the dialog.h header file which 8459262685Sdelphijcomes with the library. You may need to hack here and there to get the required 8460262685Sdelphijoutput. The source is easily customizable. I have used it on a number of 8461262685Sdelphijoccasions by modifying the code.</P 8462262685Sdelphij></DIV 8463262685Sdelphij><DIV 8464262685SdelphijCLASS="SECT2" 8465262685Sdelphij><HR><H3 8466262685SdelphijCLASS="SECT2" 8467262685Sdelphij><A 8468262685SdelphijNAME="PERLCURSES" 8469262685Sdelphij>19.3. Perl Curses Modules CURSES::FORM and CURSES::WIDGETS</A 8470262685Sdelphij></H3 8471262685Sdelphij><P 8472262685Sdelphij>The perl module Curses, Curses::Form and Curses::Widgets give access to curses 8473262685Sdelphijfrom perl. If you have curses and basic perl is installed, you can get these 8474262685Sdelphijmodules from <A 8475262685SdelphijHREF="http://www.cpan.org/modules/01modules.index.html" 8476262685SdelphijTARGET="_top" 8477262685Sdelphij> CPAN 8478262685SdelphijAll Modules page</A 8479262685Sdelphij>. Get the three zipped modules in the Curses category. 8480262685SdelphijOnce installed you can use these modules from perl scripts like any other 8481262685Sdelphijmodule. For more information on perl modules see perlmod man page. The above 8482262685Sdelphijmodules come with good documentation and they have some demo scripts to test the 8483262685Sdelphijfunctionality. Though the widgets provided are very rudimentary, these modules 8484262685Sdelphijprovide good access to curses library from perl.</P 8485262685Sdelphij><P 8486262685Sdelphij>Some of my code examples are converted to perl by Anuradha Ratnaweera and they 8487262685Sdelphijare available in the <TT 8488262685SdelphijCLASS="LITERAL" 8489262685Sdelphij>perl</TT 8490262685Sdelphij> directory.</P 8491262685Sdelphij><P 8492262685Sdelphij> 8493262685SdelphijFor more information see man pages Curses(3) , Curses::Form(3) and 8494262685SdelphijCurses::Widgets(3). These pages are installed only when the above modules are 8495262685Sdelphijacquired and installed.</P 8496262685Sdelphij></DIV 8497262685Sdelphij></DIV 8498262685Sdelphij><DIV 8499262685SdelphijCLASS="SECT1" 8500262685Sdelphij><HR><H2 8501262685SdelphijCLASS="SECT1" 8502262685Sdelphij><A 8503262685SdelphijNAME="JUSTFORFUN" 8504262685Sdelphij>20. Just For Fun !!!</A 8505262685Sdelphij></H2 8506262685Sdelphij><P 8507262685Sdelphij>This section contains few programs written by me just for fun. They don't 8508262685Sdelphijsignify a better programming practice or the best way of using ncurses. They are 8509262685Sdelphijprovided here so as to allow beginners to get ideas and add more programs to 8510262685Sdelphijthis section. If you have written a couple of nice, simple programs in curses 8511262685Sdelphijand want them to included here, contact <A 8512262685SdelphijHREF="mailto:ppadala@gmail.com" 8513262685SdelphijTARGET="_top" 8514262685Sdelphij>me</A 8515262685Sdelphij>.</P 8516262685Sdelphij><DIV 8517262685SdelphijCLASS="SECT2" 8518262685Sdelphij><HR><H3 8519262685SdelphijCLASS="SECT2" 8520262685Sdelphij><A 8521262685SdelphijNAME="GAMEOFLIFE" 8522262685Sdelphij>20.1. The Game of Life</A 8523262685Sdelphij></H3 8524262685Sdelphij><P 8525262685Sdelphij>Game of life is a wonder of math. In 8526262685Sdelphij<A 8527262685SdelphijHREF="http://www.math.com/students/wonders/life/life.html" 8528262685SdelphijTARGET="_top" 8529262685Sdelphij>Paul Callahan</A 8530262685Sdelphij>'s words</P 8531262685Sdelphij><PRE 8532262685SdelphijCLASS="PROGRAMLISTING" 8533262685Sdelphij><SPAN 8534262685SdelphijCLASS="emphasis" 8535262685Sdelphij><I 8536262685SdelphijCLASS="EMPHASIS" 8537262685Sdelphij>The Game of Life (or simply Life) is not a game in the conventional sense. There 8538166124Srafanare no players, and no winning or losing. Once the "pieces" are placed in the 8539166124Srafanstarting position, the rules determine everything that happens later. 8540166124SrafanNevertheless, Life is full of surprises! In most cases, it is impossible to look 8541166124Srafanat a starting position (or pattern) and see what will happen in the future. The 8542262685Sdelphijonly way to find out is to follow the rules of the game.</I 8543262685Sdelphij></SPAN 8544262685Sdelphij></PRE 8545262685Sdelphij><P 8546262685Sdelphij>This program starts with a simple inverted U pattern and shows how wonderful 8547262685Sdelphijlife works. There is a lot of room for improvement in the program. You can let 8548262685Sdelphijthe user enter pattern of his choice or even take input from a file. You can 8549262685Sdelphijalso change rules and play with a lot of variations. Search on <A 8550262685SdelphijHREF="http://www.google.com" 8551262685SdelphijTARGET="_top" 8552262685Sdelphij>google</A 8553262685Sdelphij> for interesting information on game 8554262685Sdelphijof life.</P 8555262685Sdelphij><P 8556262685Sdelphij><SPAN 8557262685SdelphijCLASS="emphasis" 8558262685Sdelphij><I 8559262685SdelphijCLASS="EMPHASIS" 8560262685Sdelphij>File Path: JustForFun/life.c</I 8561262685Sdelphij></SPAN 8562262685Sdelphij></P 8563262685Sdelphij></DIV 8564262685Sdelphij><DIV 8565262685SdelphijCLASS="SECT2" 8566262685Sdelphij><HR><H3 8567262685SdelphijCLASS="SECT2" 8568262685Sdelphij><A 8569262685SdelphijNAME="MAGIC" 8570262685Sdelphij>20.2. Magic Square</A 8571262685Sdelphij></H3 8572262685Sdelphij><P 8573262685Sdelphij>Magic Square, another wonder of math, is very simple to understand but very 8574262685Sdelphijdifficult to make. In a magic square sum of the numbers in each row, each column 8575262685Sdelphijis equal. Even diagnol sum can be equal. There are many variations which have 8576262685Sdelphijspecial properties.</P 8577262685Sdelphij><P 8578262685Sdelphij>This program creates a simple magic square of odd order.</P 8579262685Sdelphij><P 8580262685Sdelphij><SPAN 8581262685SdelphijCLASS="emphasis" 8582262685Sdelphij><I 8583262685SdelphijCLASS="EMPHASIS" 8584262685Sdelphij>File Path: JustForFun/magic.c</I 8585262685Sdelphij></SPAN 8586262685Sdelphij></P 8587262685Sdelphij></DIV 8588262685Sdelphij><DIV 8589262685SdelphijCLASS="SECT2" 8590262685Sdelphij><HR><H3 8591262685SdelphijCLASS="SECT2" 8592262685Sdelphij><A 8593262685SdelphijNAME="HANOI" 8594262685Sdelphij>20.3. Towers of Hanoi</A 8595262685Sdelphij></H3 8596262685Sdelphij><P 8597262685Sdelphij>The famous towers of hanoi solver. The aim of the game is to move the disks on 8598262685Sdelphijthe first peg to last peg, using middle peg as a temporary stay. The catch is 8599262685Sdelphijnot to place a larger disk over a small disk at any time.</P 8600262685Sdelphij><P 8601262685Sdelphij><SPAN 8602262685SdelphijCLASS="emphasis" 8603262685Sdelphij><I 8604262685SdelphijCLASS="EMPHASIS" 8605262685Sdelphij>File Path: JustForFun/hanoi.c</I 8606262685Sdelphij></SPAN 8607262685Sdelphij></P 8608262685Sdelphij></DIV 8609262685Sdelphij><DIV 8610262685SdelphijCLASS="SECT2" 8611262685Sdelphij><HR><H3 8612262685SdelphijCLASS="SECT2" 8613262685Sdelphij><A 8614262685SdelphijNAME="QUEENS" 8615262685Sdelphij>20.4. Queens Puzzle</A 8616262685Sdelphij></H3 8617262685Sdelphij><P 8618262685Sdelphij>The objective of the famous N-Queen puzzle is to put N queens on a N X N chess 8619262685Sdelphijboard without attacking each other. </P 8620262685Sdelphij><P 8621262685Sdelphij>This program solves it with a simple backtracking technique.</P 8622262685Sdelphij><P 8623262685Sdelphij><SPAN 8624262685SdelphijCLASS="emphasis" 8625262685Sdelphij><I 8626262685SdelphijCLASS="EMPHASIS" 8627262685Sdelphij>File Path: JustForFun/queens.c</I 8628262685Sdelphij></SPAN 8629262685Sdelphij></P 8630262685Sdelphij></DIV 8631262685Sdelphij><DIV 8632262685SdelphijCLASS="SECT2" 8633262685Sdelphij><HR><H3 8634262685SdelphijCLASS="SECT2" 8635262685Sdelphij><A 8636262685SdelphijNAME="SHUFFLE" 8637262685Sdelphij>20.5. Shuffle</A 8638262685Sdelphij></H3 8639262685Sdelphij><P 8640262685Sdelphij>A fun game, if you have time to kill. </P 8641262685Sdelphij><P 8642262685Sdelphij><SPAN 8643262685SdelphijCLASS="emphasis" 8644262685Sdelphij><I 8645262685SdelphijCLASS="EMPHASIS" 8646262685Sdelphij>File Path: JustForFun/shuffle.c</I 8647262685Sdelphij></SPAN 8648262685Sdelphij></P 8649262685Sdelphij></DIV 8650262685Sdelphij><DIV 8651262685SdelphijCLASS="SECT2" 8652262685Sdelphij><HR><H3 8653262685SdelphijCLASS="SECT2" 8654262685Sdelphij><A 8655262685SdelphijNAME="TT" 8656262685Sdelphij>20.6. Typing Tutor</A 8657262685Sdelphij></H3 8658262685Sdelphij><P 8659262685Sdelphij>A simple typing tutor, I created more out of need than for ease of use. If you 8660262685Sdelphijknow how to put your fingers correctly on the keyboard, but lack practice, this 8661262685Sdelphijcan be helpful. </P 8662262685Sdelphij><P 8663262685Sdelphij><SPAN 8664262685SdelphijCLASS="emphasis" 8665262685Sdelphij><I 8666262685SdelphijCLASS="EMPHASIS" 8667262685Sdelphij>File Path: JustForFun/tt.c</I 8668262685Sdelphij></SPAN 8669262685Sdelphij></P 8670262685Sdelphij></DIV 8671262685Sdelphij></DIV 8672262685Sdelphij><DIV 8673262685SdelphijCLASS="SECT1" 8674262685Sdelphij><HR><H2 8675262685SdelphijCLASS="SECT1" 8676262685Sdelphij><A 8677262685SdelphijNAME="REF" 8678262685Sdelphij>21. References</A 8679262685Sdelphij></H2 8680262685Sdelphij><P 8681262685Sdelphij></P 8682262685Sdelphij><UL 8683262685Sdelphij><LI 8684262685Sdelphij><P 8685262685Sdelphij>NCURSES man pages </P 8686262685Sdelphij></LI 8687262685Sdelphij><LI 8688262685Sdelphij><P 8689262685Sdelphij>NCURSES FAQ at <A 8690262685SdelphijHREF="http://invisible-island.net/ncurses/ncurses.faq.html" 8691262685SdelphijTARGET="_top" 8692262685Sdelphij>http://invisible-island.net/ncurses/ncurses.faq.html</A 8693262685Sdelphij> 8694262685Sdelphij </P 8695262685Sdelphij></LI 8696262685Sdelphij><LI 8697262685Sdelphij><P 8698262685Sdelphij>Writing programs with NCURSES by Eric Raymond and Zeyd M. 8699262685SdelphijBen-Halim at 8700262685Sdelphij<A 8701262685SdelphijHREF="http://invisible-island.net/ncurses/ncurses-intro.html" 8702262685SdelphijTARGET="_top" 8703262685Sdelphij>http://invisible-island.net/ncurses/ncurses-intro.html</A 8704262685Sdelphij> - somewhat 8705262685Sdelphijobsolete. I was inspired by this document and the structure of this HOWTO 8706262685Sdelphijfollows from the original document</P 8707262685Sdelphij></LI 8708262685Sdelphij></UL 8709262685Sdelphij></DIV 8710262685Sdelphij></DIV 8711262685Sdelphij></BODY 8712262685Sdelphij></HTML 8713262685Sdelphij>