ularn_winx11.c 73 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483
  1. /* =============================================================================
  2. * PROGRAM: ularn
  3. * FILENAME: ularn_win.c
  4. *
  5. * DESCRIPTION:
  6. * This module contains all operating system dependant code for input and
  7. * display update.
  8. * Each version of ularn should provide a different implementation of this
  9. * module.
  10. *
  11. * This is the Windows 32 window display and input module.
  12. *
  13. * =============================================================================
  14. * EXPORTED VARIABLES
  15. *
  16. * nonap : Set to true if no time delays are to be used.
  17. * nosignal : Set if ctrl-C is to be trapped to prevent exit.
  18. * enable_scroll : Probably superfluous
  19. * yrepcount : Repeat count for input commands.
  20. *
  21. * =============================================================================
  22. * EXPORTED FUNCTIONS
  23. *
  24. * init_app : Initialise the app
  25. * close_app : Close the app and free resources
  26. * get_normal_input : Get the next command input
  27. * get_prompt_input : Get input in response to a question
  28. * get_password_input : Get a password
  29. * get_num_input : Geta number
  30. * get_dir_input : Get a direction
  31. * set_display : Set the display mode
  32. * UpdateStatus : Update the status display
  33. * UpdateEffects : Update the effects display
  34. * UpdateStatusAndEffects : Update both status and effects display
  35. * ClearText : Clear the text output area
  36. * UlarnBeep : Make a beep
  37. * Cursor : Set the cursor location
  38. * Printc : Print a single character
  39. * Print : Print a string
  40. * Printf : Print a formatted string
  41. * Standout : Print a string is standout format
  42. * SetFormat : Set the output text format
  43. * ClearEOL : Clear to end of line
  44. * ClearEOPage : Clear to end of page
  45. * show1cell : Show 1 cell on the map
  46. * showplayer : Show the player on the map
  47. * showcell : Show the area around the player
  48. * drawscreen : Redraw the screen
  49. * draws : Redraw a section of the screen
  50. * mapeffect : Draw a directional effect
  51. * magic_effect_frames : Get the number of animation frames in a magic fx
  52. * magic_effect : Draw a frame in a magic fx
  53. * nap : Delay for a specified number of milliseconds
  54. * GetUser : Get teh username and user id.
  55. *
  56. * =============================================================================
  57. */
  58. #include <X11/Xlib.h>
  59. #include <X11/keysym.h>
  60. #include <X11/xpm.h>
  61. #include <stdio.h>
  62. #include <stdarg.h>
  63. #include "cursor.bm"
  64. #include "header.h"
  65. #include "ularn_game.h"
  66. #include "x11_simple_menu.h"
  67. #include "config.h"
  68. #include "dungeon.h"
  69. #include "player.h"
  70. #include "ularn_win.h"
  71. #include "monster.h"
  72. #include "itm.h"
  73. // Default size of the ularn window in characters
  74. #define WINDOW_WIDTH 80
  75. #define WINDOW_HEIGHT 25
  76. #define SEPARATOR_WIDTH 8
  77. #define SEPARATOR_HEIGHT 8
  78. #define BORDER_SIZE 8
  79. /* =============================================================================
  80. * Exported variables
  81. */
  82. int nonap = 0;
  83. int nosignal = 0;
  84. char enable_scroll = 0;
  85. int yrepcount = 0;
  86. /* =============================================================================
  87. * Local variables
  88. */
  89. #define M_NONE 0
  90. #define M_SHIFT 1
  91. #define M_CTRL 2
  92. #define M_ASCII 255
  93. #define MAX_KEY_BINDINGS 3
  94. struct KeyCodeType
  95. {
  96. int VirtKey;
  97. int ModKey;
  98. };
  99. #define NUM_DIRS 8
  100. static ActionType DirActions[NUM_DIRS] =
  101. {
  102. ACTION_MOVE_WEST,
  103. ACTION_MOVE_EAST,
  104. ACTION_MOVE_SOUTH,
  105. ACTION_MOVE_NORTH,
  106. ACTION_MOVE_NORTHEAST,
  107. ACTION_MOVE_NORTHWEST,
  108. ACTION_MOVE_SOUTHEAST,
  109. ACTION_MOVE_SOUTHWEST
  110. };
  111. /* Default keymap */
  112. /* Allow up to MAX_KEY_BINDINGS per action */
  113. static struct KeyCodeType KeyMap[ACTION_COUNT][MAX_KEY_BINDINGS] =
  114. {
  115. { { 0, 0 }, { 0, 0 }, { 0, 0 } }, // ACTION_NULL
  116. { { '~', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_DIAG
  117. { { 'h', M_ASCII }, { XK_KP_Left , M_NONE }, { XK_Left, M_NONE } }, // ACTION_MOVE_WEST
  118. { { 'H', M_ASCII }, { XK_Left, M_SHIFT }, { 0, 0 } }, // ACTION_RUN_WEST
  119. { { 'l', M_ASCII }, { XK_KP_Right, M_NONE }, { XK_Right, M_NONE } }, // ACTION_MOVE_EAST,
  120. { { 'L', M_ASCII }, { XK_Right, M_SHIFT }, { 0, 0 } }, // ACTION_RUN_EAST,
  121. { { 'j', M_ASCII }, { XK_KP_Down, M_NONE }, { XK_Down, M_NONE } }, // ACTION_MOVE_SOUTH,
  122. { { 'J', M_ASCII }, { XK_Down, M_SHIFT }, { 0, 0 } }, // ACTION_RUN_SOUTH,
  123. { { 'k', M_ASCII }, { XK_KP_Up, M_NONE }, { XK_Up, M_NONE } }, // ACTION_MOVE_NORTH,
  124. { { 'K', M_ASCII }, { XK_Up, M_SHIFT }, { 0, 0 } }, // ACTION_RUN_NORTH,
  125. { { 'u', M_ASCII }, { XK_KP_Page_Up, M_NONE }, { XK_Prior, M_NONE } }, // ACTION_MOVE_NORTHEAST,
  126. { { 'U', M_ASCII }, { XK_Prior, M_SHIFT }, { 0, 0 } }, // ACTION_RUN_NORTHEAST,
  127. { { 'y', M_ASCII }, { XK_KP_Home, M_NONE }, { XK_Home, M_NONE } }, // ACTION_MOVE_NORTHWEST,
  128. { { 'Y', M_ASCII }, { XK_Home, M_SHIFT }, { 0, 0 } }, // ACTION_RUN_NORTHWEST,
  129. { { 'n', M_ASCII }, { XK_KP_Page_Down, M_NONE }, { XK_Next, M_NONE } }, // ACTION_MOVE_SOUTHEAST,
  130. { { 'N', M_ASCII }, { XK_Next, M_SHIFT }, { 0, 0 } }, // ACTION_RUN_SOUTHEAST,
  131. { { 'b', M_ASCII }, { XK_KP_End, M_NONE }, { XK_End, M_NONE } }, // ACTION_MOVE_SOUTHWEST,
  132. { { 'B', M_ASCII }, { XK_End, M_SHIFT }, { 0, 0 } }, // ACTION_RUN_SOUTHWEST,
  133. { { '.', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_WAIT,
  134. { { ' ', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_NONE,
  135. { { 'w', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_WIELD,
  136. { { 'W', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_WEAR,
  137. { { 'r', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_READ,
  138. { { 'q', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_QUAFF,
  139. { { 'd', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_DROP,
  140. { { 'c', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_CAST_SPELL,
  141. { { 'o', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_OPEN_DOOR
  142. { { 'C', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_CLOSE_DOOR,
  143. { { 'O', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_OPEN_CHEST
  144. { { 'i', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_INVENTORY,
  145. { { 'e', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_EAT_COOKIE,
  146. { { '\\',M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_LIST_SPELLS,
  147. { { '?', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_HELP,
  148. { { 'S', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_SAVE,
  149. { { 'Z', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_TELEPORT,
  150. { { '^', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_IDENTIFY_TRAPS,
  151. { { '_', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_BECOME_CREATOR,
  152. { { '+', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_CREATE_ITEM,
  153. { { '-', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_TOGGLE_WIZARD,
  154. { { '`', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_DEBUG_MODE,
  155. { { 'T', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_REMOVE_ARMOUR,
  156. { { 'g', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_PACK_WEIGHT,
  157. { { 'v', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_VERSION,
  158. { { 'Q', M_ASCII }, { 0, 0 }, { 0, 0 } }, // ACTION_QUIT,
  159. { { 'r', M_CTRL }, { 0, 0 }, { 0, 0 } }, // ACTION_REDRAW_SCREEN,
  160. { { 'P', M_ASCII }, { 0, 0 }, { 0, 0 } } // ACTION_SHOW_TAX
  161. };
  162. static struct KeyCodeType RunKeyMap = { XK_KP_Begin, M_NONE };
  163. //
  164. // Variables for X11
  165. //
  166. #define MENU_GAME_SAVE 101
  167. #define MENU_GAME_QUIT 102
  168. #define MENU_ACTION_WAIT 201
  169. #define MENU_ACTION_WIELD 202
  170. #define MENU_ACTION_WEAR 203
  171. #define MENU_ACTION_TAKEOFF 204
  172. #define MENU_ACTION_QUAFF 205
  173. #define MENU_ACTION_READ 206
  174. #define MENU_ACTION_CAST 207
  175. #define MENU_ACTION_EAT 208
  176. #define MENU_ACTION_DROP 209
  177. #define MENU_ACTION_CLOSEDOOR 210
  178. #define MENU_SHOW_DISCOVERIES 301
  179. #define MENU_SHOW_INVENTORY 302
  180. #define MENU_SHOW_TAX 303
  181. #define MENU_SHOW_PACKWEIGHT 304
  182. #define MENU_DISPLAY_REDRAW 401
  183. #define MENU_DISPLAY_BEEP 402
  184. #define MENU_DISPLAY_FONT 403
  185. #define MENU_HELP_HELP 501
  186. #define MENU_HELP_VERSION 502
  187. #define MENU_HELP_ABOUT 503
  188. /* Help menu definitions */
  189. struct XMENU_Item Help_About_Item = /* unused */
  190. {
  191. "About", MENU_HELP_ABOUT, XMENU_UNCHECKED, NULL
  192. };
  193. struct XMENU_Item Help_Version_Item =
  194. {
  195. "Version", MENU_HELP_VERSION, XMENU_UNCHECKED, NULL
  196. };
  197. struct XMENU_Item Help_Help_Item =
  198. {
  199. "Help", MENU_HELP_HELP, XMENU_UNCHECKED, &Help_Version_Item
  200. };
  201. struct XMENU_Menu Help_Menu =
  202. {
  203. "Help",
  204. NULL,
  205. &Help_Help_Item,
  206. 0, 0, 0, 0
  207. };
  208. /* Display menu definitions */
  209. struct XMENU_Item Display_Font_Item = /* unused */
  210. {
  211. "Font", MENU_DISPLAY_FONT, XMENU_UNCHECKED, NULL
  212. };
  213. struct XMENU_Item Display_Beep_Item =
  214. {
  215. "Beep", MENU_DISPLAY_BEEP, XMENU_UNCHECKED, NULL
  216. };
  217. struct XMENU_Item Display_Redraw_Item =
  218. {
  219. "Redraw", MENU_DISPLAY_REDRAW, XMENU_UNCHECKED, &Display_Beep_Item
  220. };
  221. struct XMENU_Menu Display_Menu =
  222. {
  223. "Display",
  224. &Help_Menu,
  225. &Display_Redraw_Item,
  226. 0, 0, 0, 0
  227. };
  228. /* Show menu definitions */
  229. struct XMENU_Item Show_Packweight_Item =
  230. {
  231. "Pack weight", MENU_SHOW_PACKWEIGHT, XMENU_UNCHECKED, NULL
  232. };
  233. struct XMENU_Item Show_Tax_Item =
  234. {
  235. "Tax", MENU_SHOW_TAX, XMENU_UNCHECKED, &Show_Packweight_Item
  236. };
  237. struct XMENU_Item Show_Inventory_Item =
  238. {
  239. "Inventory", MENU_SHOW_INVENTORY, XMENU_UNCHECKED, &Show_Tax_Item
  240. };
  241. struct XMENU_Item Show_Discoveries_Item =
  242. {
  243. "Discoveries", MENU_SHOW_DISCOVERIES, XMENU_UNCHECKED, &Show_Inventory_Item
  244. };
  245. struct XMENU_Menu Show_Menu =
  246. {
  247. "Show",
  248. &Display_Menu,
  249. &Show_Discoveries_Item,
  250. 0, 0, 0, 0
  251. };
  252. /* Action Menu definitions */
  253. struct XMENU_Item Action_Closedoor_Item =
  254. {
  255. "Close door", MENU_ACTION_CLOSEDOOR, XMENU_UNCHECKED, NULL
  256. };
  257. struct XMENU_Item Action_Drop_Item =
  258. {
  259. "Drop", MENU_ACTION_DROP, XMENU_UNCHECKED, &Action_Closedoor_Item
  260. };
  261. struct XMENU_Item Action_Eat_Item =
  262. {
  263. "Eat", MENU_ACTION_EAT, XMENU_UNCHECKED, &Action_Drop_Item
  264. };
  265. struct XMENU_Item Action_Cast_Item =
  266. {
  267. "Cast", MENU_ACTION_CAST, XMENU_UNCHECKED, &Action_Eat_Item
  268. };
  269. struct XMENU_Item Action_Read_Item =
  270. {
  271. "Read", MENU_ACTION_READ, XMENU_UNCHECKED, &Action_Cast_Item
  272. };
  273. struct XMENU_Item Action_Quaff_Item =
  274. {
  275. "Quaff", MENU_ACTION_QUAFF, XMENU_UNCHECKED, &Action_Read_Item
  276. };
  277. struct XMENU_Item Action_Takeoff_Item =
  278. {
  279. "Take off", MENU_ACTION_TAKEOFF, XMENU_UNCHECKED, &Action_Quaff_Item
  280. };
  281. struct XMENU_Item Action_Wear_Item =
  282. {
  283. "Wear", MENU_ACTION_WEAR, XMENU_UNCHECKED, &Action_Takeoff_Item
  284. };
  285. struct XMENU_Item Action_Wield_Item =
  286. {
  287. "Wield", MENU_ACTION_WIELD, XMENU_UNCHECKED, &Action_Wear_Item
  288. };
  289. struct XMENU_Item Action_Wait_Item =
  290. {
  291. "Wait", MENU_ACTION_WAIT, XMENU_UNCHECKED, &Action_Wield_Item
  292. };
  293. struct XMENU_Menu Action_Menu =
  294. {
  295. "Action",
  296. &Show_Menu,
  297. &Action_Wait_Item,
  298. 0, 0, 0, 0
  299. };
  300. /* Game menu definitions */
  301. struct XMENU_Item Game_Quit_Item =
  302. {
  303. "Quit", MENU_GAME_QUIT, XMENU_UNCHECKED, NULL
  304. };
  305. struct XMENU_Item Game_Save_Item =
  306. {
  307. "Save", MENU_GAME_SAVE, XMENU_UNCHECKED, &Game_Quit_Item
  308. };
  309. struct XMENU_Menu Game_Menu =
  310. {
  311. "Game",
  312. &Action_Menu,
  313. &Game_Save_Item,
  314. 0, 0, 0, 0
  315. };
  316. int ularn_menu_height;
  317. #define INITIAL_WIDTH 400
  318. #define INITIAL_HEIGHT 300
  319. static Display *display = NULL;
  320. static int screen_num;
  321. static int screen_width;
  322. static int screen_height;
  323. static Window root_window = None;
  324. static Window ularn_window = None;
  325. static GC ularn_gc = None;
  326. static XGCValues gc_values;
  327. static unsigned long gc_values_mask;
  328. static unsigned long white_pixel;
  329. static unsigned long black_pixel;
  330. static Colormap colormap;
  331. static XColor LtGrey;
  332. static XColor MidGrey;
  333. static XColor DkGrey;
  334. static XColor Red;
  335. static XColor Green;
  336. static XColor Blue;
  337. static XFontStruct *font_info;
  338. char * font_name = "*-courier-medium-r-*-12-*";
  339. static Pixmap TilePixmap = None;
  340. static Pixmap TilePShape = None;
  341. static XpmAttributes TileAttributes;
  342. static Pixmap CursorPixmap = None;
  343. static int CaretActive = 0;
  344. static int TileWidth = 32;
  345. static int TileHeight = 32;
  346. static int CharHeight;
  347. static int CharWidth;
  348. static int CharAscent;
  349. static int LarnWindowWidth = INITIAL_WIDTH;
  350. static int LarnWindowHeight = INITIAL_HEIGHT;
  351. static int MinWindowWidth;
  352. static int MinWindowHeight;
  353. static int Runkey;
  354. static ActionType Event;
  355. static int GotChar;
  356. static char EventChar;
  357. //
  358. // Bitmaps for tiles
  359. //
  360. static char *TileFilename = LIBDIR "/vlarn_gfx.xpm";
  361. /* Tiles for different character classes, (female, male) */
  362. static int PlayerTiles[8][2] =
  363. {
  364. { 165, 181 }, /* Ogre */
  365. { 166, 182 }, /* Wizard */
  366. { 167, 183 }, /* Klingon */
  367. { 168, 184 }, /* Elf */
  368. { 169, 185 }, /* Rogue */
  369. { 170, 186 }, /* Adventurer */
  370. { 171, 187 }, /* Dwarf */
  371. { 172, 188 } /* Rambo */
  372. };
  373. #define TILE_CURSOR1 174
  374. #define TILE_CURSOR2 190
  375. #define WALL_TILES 352
  376. /* Tiles for directional effects */
  377. static int EffectTile[EFFECT_COUNT][9] =
  378. {
  379. { 191, 198, 196, 194, 192, 195, 193, 197, 199 },
  380. { 191, 206, 204, 202, 200, 203, 201, 205, 207 },
  381. { 191, 214, 212, 210, 208, 211, 209, 213, 215 },
  382. { 191, 222, 220, 218, 216, 219, 217, 221, 223 },
  383. { 191, 230, 228, 226, 224, 227, 225, 229, 231 }
  384. };
  385. #define MAX_MAGICFX_FRAME 8
  386. struct MagicEffectDataType
  387. {
  388. int Overlay; /* 0 = no overlay, 1 = overlay */
  389. int Frames; /* Number of frames in the effect */
  390. int Tile1[MAX_MAGICFX_FRAME]; /* The primary tile for this frame */
  391. int Tile2[MAX_MAGICFX_FRAME]; /* Only used for overlay effects */
  392. };
  393. static struct MagicEffectDataType magicfx_tile[MAGIC_COUNT] =
  394. {
  395. /* Sparkle */
  396. { 1, /* Overlay this on current tile */
  397. 8,
  398. { 240, 241, 242, 243, 244, 245, 246, 247 },
  399. { 248, 249, 250, 251, 252, 253, 254, 255 }
  400. },
  401. /* Sleep */
  402. {
  403. 0,
  404. 6,
  405. { 256, 272, 288, 304, 320, 336, 0, 0 },
  406. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  407. },
  408. /* Web */
  409. {
  410. 0,
  411. 6,
  412. { 257, 273, 289, 305, 321, 337, 0, 0 },
  413. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  414. },
  415. /* Phantasmal forces */
  416. {
  417. 0,
  418. 6,
  419. { 258, 274, 290, 306, 322, 338, 0, 0 },
  420. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  421. },
  422. /* Cloud kill */
  423. {
  424. 0,
  425. 6,
  426. { 259, 275, 291, 307, 323, 339, 0, 0 },
  427. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  428. },
  429. /* Vaporize rock */
  430. {
  431. 0,
  432. 6,
  433. { 260, 276, 292, 308, 324, 340, 0, 0 },
  434. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  435. },
  436. /* Dehydrate */
  437. {
  438. 0,
  439. 6,
  440. { 261, 277, 293, 309, 325, 341, 0, 0 },
  441. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  442. },
  443. /* Drain life */
  444. {
  445. 0,
  446. 6,
  447. { 262, 278, 294, 310, 326, 342, 0, 0 },
  448. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  449. },
  450. /* Flood */
  451. {
  452. 0,
  453. 6,
  454. { 263, 279, 295, 311, 327, 343, 0, 0 },
  455. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  456. },
  457. /* Finger of death */
  458. {
  459. 0,
  460. 6,
  461. { 264, 280, 296, 312, 328, 344, 0, 0 },
  462. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  463. },
  464. /* Teleport away */
  465. {
  466. 0,
  467. 6,
  468. { 265, 281, 297, 313, 329, 345, 0, 0 },
  469. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  470. },
  471. /* Magic fire */
  472. {
  473. 0,
  474. 6,
  475. { 266, 282, 298, 314, 330, 346, 0, 0 },
  476. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  477. },
  478. /* Make wall */
  479. {
  480. 0,
  481. 6,
  482. { 267, 283, 299, 315, 331, 347, 0, 0 },
  483. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  484. },
  485. /* Summon demon */
  486. {
  487. 0,
  488. 6,
  489. { 268, 284, 300, 316, 332, 348, 0, 0 },
  490. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  491. },
  492. /* Annihilate (scroll) */
  493. {
  494. 0,
  495. 6,
  496. { 269, 285, 301, 317, 333, 349, 0, 0 },
  497. { 0, 0, 0, 0, 0, 0 ,0 ,0 }
  498. }
  499. };
  500. //
  501. // Current display mode
  502. //
  503. DisplayModeType CurrentDisplayMode = DISPLAY_TEXT;
  504. //
  505. // Map window position and size
  506. //
  507. static int MapLeft;
  508. static int MapTop;
  509. static int MapAreaLeft;
  510. static int MapAreaTop;
  511. static int MapWidth;
  512. static int MapHeight;
  513. static int MapTileLeft = 0;
  514. static int MapTileTop = 0;
  515. static int MapTileWidth;
  516. static int MapTileHeight;
  517. //
  518. // Status lines window position and size
  519. //
  520. static int StatusLeft;
  521. static int StatusTop;
  522. static int StatusWidth;
  523. static int StatusHeight;
  524. //
  525. // Effects window position and size
  526. //
  527. static int EffectsLeft;
  528. static int EffectsTop;
  529. static int EffectsWidth;
  530. static int EffectsHeight;
  531. //
  532. // Message window position and size
  533. //
  534. static int MessageLeft;
  535. static int MessageTop;
  536. static int MessageWidth;
  537. static int MessageHeight;
  538. //
  539. // Text window position, size
  540. //
  541. static int TextLeft;
  542. static int TextTop;
  543. static int TextWidth;
  544. static int TextHeight;
  545. static int ShowTextBorder;
  546. // =============================================================================
  547. // Text mode stuff
  548. //
  549. #define LINE_LENGTH 80
  550. typedef char TextLine[LINE_LENGTH + 1];
  551. typedef FormatType FormatLine[LINE_LENGTH + 1];
  552. //
  553. // Messages
  554. //
  555. #define MAX_MSG_LINES 5
  556. static TextLine MessageChr[MAX_MSG_LINES];
  557. static FormatLine MessageFmt[MAX_MSG_LINES];
  558. static FormatType CurrentMsgFormat;
  559. static int MsgCursorX = 1;
  560. static int MsgCursorY = 1;
  561. //
  562. // Text
  563. //
  564. #define MAX_TEXT_LINES 25
  565. #define TEXT_LINE_LENGTH 80
  566. static TextLine TextChr[MAX_TEXT_LINES];
  567. static FormatLine TextFmt[MAX_TEXT_LINES];
  568. static FormatType CurrentTextFormat;
  569. static int TextCursorX = 1;
  570. static int TextCursorY = 1;
  571. //
  572. // Generalised text buffer
  573. // Top left corner is x=1, y=1
  574. //
  575. static TextLine *Text;
  576. static FormatLine *Format;
  577. static FormatType CurrentFormat;
  578. static int CursorX = 1;
  579. static int CursorY = 1;
  580. static int MaxLine;
  581. static int TTop;
  582. static int TLeft;
  583. static int TWidth;
  584. static int THeight;
  585. //
  586. // The monster to use for showing mimics. Changes every 10 turns.
  587. //
  588. static int mimicmonst = MIMIC;
  589. /* =============================================================================
  590. * Local functions
  591. */
  592. /* =============================================================================
  593. * FUNCTION: calc_scroll
  594. *
  595. * DESCRIPTION:
  596. * Calculate the new scroll position of the map based on the player's current
  597. * position.
  598. *
  599. * PARAMETERS:
  600. *
  601. * None.
  602. *
  603. * RETURN VALUE:
  604. *
  605. * true if the new scroll position differs from the previous scroll position.
  606. */
  607. static int calc_scroll(void)
  608. {
  609. int ox, oy;
  610. ox = MapTileLeft;
  611. oy = MapTileTop;
  612. if (MapTileHeight < MAXY)
  613. {
  614. MapTileTop = playery - MapTileHeight / 2;
  615. if (MapTileTop < 0)
  616. {
  617. MapTileTop = 0;
  618. }
  619. if ((MapTileTop + MapTileHeight) > MAXY)
  620. {
  621. MapTileTop = MAXY - MapTileHeight;
  622. }
  623. }
  624. else
  625. {
  626. MapTileTop = 0;
  627. }
  628. if (MapTileWidth < MAXX)
  629. {
  630. MapTileLeft = playerx - MapTileWidth / 2;
  631. if (MapTileLeft < 0)
  632. {
  633. MapTileLeft = 0;
  634. }
  635. if ((MapTileLeft + MapTileWidth) > MAXX)
  636. {
  637. MapTileLeft = MAXX - MapTileWidth;
  638. }
  639. }
  640. else
  641. {
  642. MapTileLeft = 0;
  643. }
  644. //
  645. // return true if the map requires scrolling
  646. //
  647. return ((MapTileLeft != ox) || (MapTileTop != oy));
  648. }
  649. /* =============================================================================
  650. * FUNCTION: CalcMinWindowSize
  651. *
  652. * DESCRIPTION:
  653. * Calculate the minimum window size.
  654. * The new minimum windows size is stored in MinWindowWidth and MinWindowHeight.
  655. * If the current window size is smaller than this then it is resized.
  656. *
  657. * PARAMETERS:
  658. *
  659. * None.
  660. *
  661. * RETURN VALUE:
  662. *
  663. * None.
  664. */
  665. static void CalcMinWindowSize(void)
  666. {
  667. XSizeHints size_hints;
  668. CharWidth = font_info->max_bounds.width;
  669. CharHeight = font_info->max_bounds.ascent + font_info->max_bounds.descent;
  670. CharAscent = font_info->max_bounds.ascent;
  671. MinWindowWidth =
  672. WINDOW_WIDTH * CharWidth;
  673. MinWindowHeight =
  674. WINDOW_HEIGHT * CharHeight +
  675. 2 * SEPARATOR_HEIGHT +
  676. ularn_menu_height;
  677. //
  678. // Update the window size
  679. //
  680. if (MinWindowWidth > LarnWindowWidth)
  681. {
  682. LarnWindowWidth = MinWindowWidth;
  683. }
  684. if (MinWindowHeight > LarnWindowHeight)
  685. {
  686. LarnWindowHeight = MinWindowHeight;
  687. }
  688. size_hints.flags = PMinSize | PBaseSize;
  689. size_hints.min_width = MinWindowWidth;
  690. size_hints.min_height = MinWindowHeight;
  691. size_hints.base_width = LarnWindowWidth;
  692. size_hints.base_height = LarnWindowHeight;
  693. XSetNormalHints(display, ularn_window, &size_hints);
  694. XResizeWindow(display, ularn_window, LarnWindowWidth, LarnWindowHeight);
  695. }
  696. /*
  697. * Repaint flag to force redraw of everything, not just deltas
  698. */
  699. static int Repaint = 0;
  700. /* =============================================================================
  701. * FUNCTION: PaintStatus
  702. *
  703. * DESCRIPTION:
  704. * Paint the status area.
  705. *
  706. * PARAMETERS:
  707. *
  708. * None.
  709. *
  710. * RETURN VALUE:
  711. *
  712. * None.
  713. */
  714. static void PaintStatus(void)
  715. {
  716. char Line[81];
  717. char Buf[81];
  718. int i;
  719. XSetForeground(display, ularn_gc, white_pixel);
  720. XSetBackground(display, ularn_gc, black_pixel);
  721. XSetFillStyle(display, ularn_gc, FillSolid);
  722. XFillRectangle(display, ularn_window, ularn_gc, StatusLeft, StatusTop, StatusWidth, StatusHeight);
  723. XSetForeground(display, ularn_gc, black_pixel);
  724. XSetBackground(display, ularn_gc, white_pixel);
  725. XSetFillStyle(display, ularn_gc, FillSolid);
  726. //
  727. // Build the top status line
  728. //
  729. Line[0] = 0;
  730. /* Spells */
  731. if (c[SPELLMAX]>99)
  732. sprintf(Buf, "Spells:%3ld(%3ld)", c[SPELLS],c[SPELLMAX]);
  733. else
  734. sprintf(Buf, "Spells:%3ld(%2ld) ",c[SPELLS],c[SPELLMAX]);
  735. strcat(Line, Buf);
  736. /* AC, WC */
  737. sprintf(Buf, " AC: %-3ld WC: %-3ld Level", c[AC], c[WCLASS]);
  738. strcat(Line, Buf);
  739. /* Level */
  740. if (c[LEVEL]>99)
  741. sprintf(Buf, "%3ld", c[LEVEL]);
  742. else
  743. sprintf(Buf, " %-2ld", c[LEVEL]);
  744. strcat(Line, Buf);
  745. /* Exp, class */
  746. sprintf(Buf, " Exp: %-9ld %s", c[EXPERIENCE], class[c[LEVEL]-1]);
  747. strcat(Line, Buf);
  748. XDrawString(display, ularn_window, ularn_gc,
  749. StatusLeft,
  750. StatusTop + CharAscent,
  751. Line,
  752. strlen(Line));
  753. //
  754. // Format the second line of the status
  755. //
  756. sprintf(Buf, "%ld (%ld)", c[HP], c[HPMAX]);
  757. sprintf(Line, "HP: %11s STR=%-2ld INT=%-2ld WIS=%-2ld CON=%-2ld DEX=%-2ld CHA=%-2ld LV:",
  758. Buf,
  759. c[STRENGTH]+c[STREXTRA],
  760. c[INTELLIGENCE],
  761. c[WISDOM],
  762. c[CONSTITUTION],
  763. c[DEXTERITY],
  764. c[CHARISMA]);
  765. if ((level==0) || (wizard))
  766. c[TELEFLAG]=0;
  767. if (c[TELEFLAG])
  768. strcat(Line, " ?");
  769. else
  770. strcat(Line, levelname[level]);
  771. sprintf(Buf, " Gold: %-8ld", c[GOLD]);
  772. strcat(Line, Buf);
  773. XDrawString(display, ularn_window, ularn_gc,
  774. StatusLeft,
  775. StatusTop + CharHeight + CharAscent,
  776. Line,
  777. strlen(Line));
  778. //
  779. // Mark all character values as displayed.
  780. //
  781. c[TMP] = c[STRENGTH]+c[STREXTRA];
  782. for (i=0; i<100; i++)
  783. cbak[i]=c[i];
  784. }
  785. /* Effects strings */
  786. static struct bot_side_def
  787. {
  788. int typ;
  789. char *string;
  790. } bot_data[] =
  791. {
  792. { STEALTH, "Stealth " },
  793. { UNDEADPRO, "Undead Pro" },
  794. { SPIRITPRO, "Spirit Pro" },
  795. { CHARMCOUNT, "Charm " },
  796. { TIMESTOP, "Time Stop " },
  797. { HOLDMONST, "Hold Monst" },
  798. { GIANTSTR, "Giant Str " },
  799. { FIRERESISTANCE, "Fire Resit" },
  800. { DEXCOUNT, "Dexterity " },
  801. { STRCOUNT, "Strength " },
  802. { SCAREMONST, "Scare " },
  803. { HASTESELF, "Haste Self" },
  804. { CANCELLATION, "Cancel " },
  805. { INVISIBILITY, "Invisible " },
  806. { ALTPRO, "Protect 3 " },
  807. { PROTECTIONTIME, "Protect 2 " },
  808. { WTW, "Wall-Walk " }
  809. };
  810. /* =============================================================================
  811. * FUNCTION: PaintEffects
  812. *
  813. * DESCRIPTION:
  814. * Paint the effects display.
  815. *
  816. * PARAMETERS:
  817. *
  818. * None.
  819. *
  820. * RETURN VALUE:
  821. *
  822. * None.
  823. */
  824. static void PaintEffects(void)
  825. {
  826. int i, idx;
  827. int WasSet;
  828. int IsSet;
  829. if (Repaint)
  830. {
  831. XSetForeground(display, ularn_gc, white_pixel);
  832. XSetBackground(display, ularn_gc, black_pixel);
  833. XSetFillStyle(display, ularn_gc, FillSolid);
  834. XFillRectangle(display, ularn_window, ularn_gc, EffectsLeft, EffectsTop, EffectsWidth, EffectsHeight);
  835. }
  836. for (i=0; i < 17; i++)
  837. {
  838. idx = bot_data[i].typ;
  839. WasSet = (cbak[idx] != 0);
  840. IsSet = (c[idx] != 0);
  841. if ((Repaint) || (IsSet != WasSet))
  842. {
  843. if (IsSet)
  844. {
  845. XSetForeground(display, ularn_gc, black_pixel);
  846. XSetBackground(display, ularn_gc, white_pixel);
  847. XSetFillStyle(display, ularn_gc, FillSolid);
  848. XDrawString(display, ularn_window, ularn_gc,
  849. EffectsLeft,
  850. EffectsTop + i * CharHeight + CharAscent,
  851. bot_data[i].string, strlen(bot_data[i].string));
  852. }
  853. else
  854. {
  855. XSetForeground(display, ularn_gc, white_pixel);
  856. XSetBackground(display, ularn_gc, black_pixel);
  857. XSetFillStyle(display, ularn_gc, FillSolid);
  858. XFillRectangle(display, ularn_window, ularn_gc,
  859. EffectsLeft, EffectsTop + i * CharHeight,
  860. EffectsWidth, CharHeight);
  861. }
  862. }
  863. cbak[idx] = c[idx];
  864. }
  865. }
  866. /* =============================================================================
  867. * FUNCTION: GetTile
  868. *
  869. * DESCRIPTION:
  870. * Get the tile to be displayed for a location on the map.
  871. *
  872. * PARAMETERS:
  873. *
  874. * x : The x coordinate for the tile
  875. *
  876. * y : The y coordiante for the tile
  877. *
  878. * TileId : This is set to the tile to be displayed for (x, y).
  879. *
  880. * RETURN VALUE:
  881. *
  882. * None.
  883. */
  884. static void GetTile(int x, int y, int *TileId)
  885. {
  886. MonsterIdType k;
  887. if ((x == playerx) && (y == playery) && (c[BLINDCOUNT] == 0))
  888. {
  889. //
  890. // This is the square containing the player and the players isn't
  891. // blind, so return the player tile.
  892. //
  893. *TileId = PlayerTiles[class_num][(int) sex];
  894. return;
  895. }
  896. //
  897. // Work out what is here
  898. //
  899. if (know[x][y] == OUNKNOWN)
  900. {
  901. //
  902. // The player doesn't know what is at this position.
  903. //
  904. *TileId = objtilelist[OUNKNOWN];
  905. }
  906. else
  907. {
  908. k = mitem[x][y].mon;
  909. if (k != 0)
  910. {
  911. if ((c[BLINDCOUNT] == 0) &&
  912. (((stealth[x][y] & STEALTH_SEEN) != 0) ||
  913. ((stealth[x][y] & STEALTH_AWAKE) != 0)))
  914. {
  915. //
  916. // There is a monster here and the player is not blind and the
  917. // monster is seen or awake.
  918. //
  919. if (k == MIMIC)
  920. {
  921. if ((gtime % 10) == 0)
  922. {
  923. while ((mimicmonst = rnd(MAXMONST))==INVISIBLESTALKER);
  924. }
  925. *TileId = monsttilelist[mimicmonst];
  926. }
  927. else if ((k==INVISIBLESTALKER) && (c[SEEINVISIBLE]==0))
  928. {
  929. *TileId = objtilelist[(int) know[x][y]];
  930. }
  931. else if ((k>=DEMONLORD) && (k<=LUCIFER) && (c[EYEOFLARN]==0))
  932. {
  933. /* demons are invisible if not have the eye */
  934. *TileId = objtilelist[(int) know[x][y]];
  935. }
  936. else
  937. {
  938. *TileId = monsttilelist[k];
  939. }
  940. } /* can see monster */
  941. else
  942. {
  943. /*
  944. * The monster at this location is not known to the player, so show
  945. * the tile for the item at this location
  946. */
  947. *TileId = objtilelist[(int) know[x][y]];
  948. }
  949. } /* monster here */
  950. else
  951. {
  952. k = know[x][y];
  953. *TileId = objtilelist[k];
  954. }
  955. }
  956. /* Handle walls */
  957. if (*TileId == objtilelist[OWALL])
  958. {
  959. *TileId = WALL_TILES + iarg[x][y];
  960. }
  961. }
  962. /* =============================================================================
  963. * FUNCTION: PaintMap
  964. *
  965. * DESCRIPTION:
  966. * Repaint the map.
  967. *
  968. * PARAMETERS:
  969. *
  970. * None.
  971. *
  972. * RETURN VALUE:
  973. *
  974. * None.
  975. */
  976. static void PaintMap(void)
  977. {
  978. int x, y;
  979. int sx, sy;
  980. int mx, my;
  981. int TileId;
  982. int TileX;
  983. int TileY;
  984. if (Repaint)
  985. {
  986. XSetForeground(display, ularn_gc, black_pixel);
  987. XFillRectangle(display, ularn_window, ularn_gc, MapAreaLeft, MapAreaTop, MapWidth, MapHeight);
  988. }
  989. mx = MapTileLeft + MapTileWidth;
  990. my = MapTileTop + MapTileHeight;
  991. if (my > MAXY)
  992. {
  993. my = MAXY;
  994. }
  995. if (mx > MAXX)
  996. {
  997. mx = MAXX;
  998. }
  999. sx = 0;
  1000. for (x = MapTileLeft ; x < mx ; x++)
  1001. {
  1002. sy = 0;
  1003. for (y = MapTileTop ; y < my ; y++)
  1004. {
  1005. GetTile(x, y, &TileId);
  1006. TileX = (TileId % 16) * TileWidth;
  1007. TileY = (TileId / 16) * TileHeight;
  1008. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  1009. TileX, TileY,
  1010. TileWidth, TileHeight,
  1011. MapLeft + sx*TileWidth, MapTop + sy*TileHeight);
  1012. sy++;
  1013. }
  1014. sx++;
  1015. }
  1016. sx = playerx - MapTileLeft;
  1017. sy = playery - MapTileTop;
  1018. if ((sx >= 0) && (sx < MapTileWidth) &&
  1019. (sy >= 0) && (sy < MapTileHeight))
  1020. {
  1021. TileId = TILE_CURSOR1;
  1022. TileX = (TileId % 16) * TileWidth;
  1023. TileY = (TileId / 16) * TileHeight;
  1024. XSetClipOrigin(display, ularn_gc,
  1025. MapLeft + sx*TileWidth - TileX,
  1026. MapTop + sy*TileHeight - TileY);
  1027. XSetClipMask(display, ularn_gc, TilePShape);
  1028. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  1029. TileX, TileY,
  1030. TileWidth, TileHeight,
  1031. MapLeft + sx*TileWidth,
  1032. MapTop + sy*TileHeight);
  1033. XSetClipOrigin(display, ularn_gc, 0, 0);
  1034. XSetClipMask(display, ularn_gc, None);
  1035. }
  1036. }
  1037. /* =============================================================================
  1038. * FUNCTION: PaintTextWindow
  1039. *
  1040. * DESCRIPTION:
  1041. * Repaint the window in text mode.
  1042. *
  1043. * PARAMETERS:
  1044. *
  1045. * None.
  1046. *
  1047. * RETURN VALUE:
  1048. *
  1049. * None.
  1050. */
  1051. static void PaintTextWindow(void)
  1052. {
  1053. int sx, ex, y;
  1054. FormatType Fmt;
  1055. int FillX, FillY;
  1056. int FillWidth, FillHeight;
  1057. XGCValues values;
  1058. FillX = TLeft;
  1059. FillY = TTop;
  1060. FillWidth = TWidth;
  1061. FillHeight = THeight;
  1062. if (CurrentDisplayMode == DISPLAY_TEXT)
  1063. {
  1064. if (ShowTextBorder)
  1065. {
  1066. //
  1067. // Clear the drawable area
  1068. //
  1069. FillX = 0;
  1070. FillY = ularn_menu_height;
  1071. FillWidth = LarnWindowWidth;
  1072. FillHeight = LarnWindowHeight - ularn_menu_height;
  1073. XSetForeground(display, ularn_gc, black_pixel);
  1074. XSetBackground(display, ularn_gc, white_pixel);
  1075. XSetFillStyle(display, ularn_gc, FillSolid);
  1076. XFillRectangle(display, ularn_window, ularn_gc,
  1077. FillX, FillY, FillWidth, FillHeight);
  1078. XSetForeground(display, ularn_gc, white_pixel);
  1079. XSetBackground(display, ularn_gc, black_pixel);
  1080. values.line_width = 2;
  1081. XChangeGC(display, ularn_gc, GCLineWidth, &values);
  1082. XDrawArc(display, ularn_window, ularn_gc,
  1083. TLeft - 8, TTop - 8, 16, 16,
  1084. 90 * 64, 90 * 64);
  1085. XDrawArc(display, ularn_window, ularn_gc,
  1086. TLeft - 8, TTop + THeight - 8, 16, 16,
  1087. 180 * 64, 90 * 64);
  1088. XDrawArc(display, ularn_window, ularn_gc,
  1089. TLeft + TWidth - 8, TTop - 8, 16, 16,
  1090. 0 * 64, 90 * 64);
  1091. XDrawArc(display, ularn_window, ularn_gc,
  1092. TLeft + TWidth - 8, TTop + THeight - 8, 16, 16,
  1093. 270 * 64, 90 * 64);
  1094. XDrawLine(display, ularn_window, ularn_gc,
  1095. TLeft, TTop - 8,
  1096. TLeft + TWidth, TTop - 8);
  1097. XDrawLine(display, ularn_window, ularn_gc,
  1098. TLeft, TTop + THeight + 8,
  1099. TLeft + TWidth, TTop + THeight + 8);
  1100. XDrawLine(display, ularn_window, ularn_gc,
  1101. TLeft - 8 , TTop,
  1102. TLeft - 8, TTop + THeight);
  1103. XDrawLine(display, ularn_window, ularn_gc,
  1104. TLeft + TWidth + 8, TTop,
  1105. TLeft + TWidth + 8, TTop + THeight);
  1106. values.line_width = 0;
  1107. XChangeGC(display, ularn_gc, GCLineWidth, &values);
  1108. FillX = TLeft;
  1109. FillY = TTop;
  1110. FillWidth = TWidth;
  1111. FillHeight = THeight;
  1112. }
  1113. else
  1114. {
  1115. //
  1116. // Not enough space around the text area for a border
  1117. // Fill the entire drawable area
  1118. //
  1119. FillX = 0;
  1120. FillY = ularn_menu_height;
  1121. FillWidth = LarnWindowWidth;
  1122. FillHeight = LarnWindowHeight - ularn_menu_height;
  1123. }
  1124. }
  1125. XSetForeground(display, ularn_gc, white_pixel);
  1126. XSetBackground(display, ularn_gc, black_pixel);
  1127. XSetFillStyle(display, ularn_gc, FillSolid);
  1128. XFillRectangle(display, ularn_window, ularn_gc,
  1129. FillX, FillY, FillWidth, FillHeight);
  1130. XSetForeground(display, ularn_gc, black_pixel);
  1131. XSetBackground(display, ularn_gc, white_pixel);
  1132. XSetFillStyle(display, ularn_gc, FillSolid);
  1133. for (y = 0 ; y < MaxLine ; y++)
  1134. {
  1135. sx = 0;
  1136. while (sx < LINE_LENGTH)
  1137. {
  1138. Fmt = Format[y][sx];
  1139. ex = sx;
  1140. while ((ex < LINE_LENGTH) && (Format[y][ex] == Fmt)) ex++;
  1141. switch (Fmt)
  1142. {
  1143. case FORMAT_NORMAL:
  1144. XSetForeground(display, ularn_gc, black_pixel);
  1145. break;
  1146. case FORMAT_STANDOUT:
  1147. XSetForeground(display, ularn_gc, Red.pixel);
  1148. break;
  1149. case FORMAT_STANDOUT2:
  1150. XSetForeground(display, ularn_gc, Green.pixel);
  1151. break;
  1152. case FORMAT_STANDOUT3:
  1153. XSetForeground(display, ularn_gc, Blue.pixel);
  1154. break;
  1155. default:
  1156. break;
  1157. }
  1158. XDrawString(display, ularn_window, ularn_gc,
  1159. TLeft + sx * CharWidth,
  1160. TTop + y * CharHeight + CharAscent,
  1161. Text[y] + sx,
  1162. ex - sx);
  1163. sx = ex;
  1164. }
  1165. }
  1166. }
  1167. /* =============================================================================
  1168. * FUNCTION: PaintMapWindow
  1169. *
  1170. * DESCRIPTION:
  1171. * Repaint the window in map mode
  1172. *
  1173. * PARAMETERS:
  1174. *
  1175. * None.
  1176. *
  1177. * RETURN VALUE:
  1178. *
  1179. * None.
  1180. */
  1181. static void PaintMapWindow(void)
  1182. {
  1183. //
  1184. // Draw separators between the different window areas
  1185. //
  1186. //
  1187. // Message area
  1188. //
  1189. XSetForeground(display, ularn_gc, LtGrey.pixel);
  1190. XFillRectangle(display, ularn_window, ularn_gc,
  1191. MessageLeft, MessageTop - SEPARATOR_HEIGHT,
  1192. MessageWidth, 2);
  1193. XSetForeground(display, ularn_gc, MidGrey.pixel);
  1194. XFillRectangle(display, ularn_window, ularn_gc,
  1195. MessageLeft, MessageTop - SEPARATOR_HEIGHT + 2,
  1196. MessageWidth, 4);
  1197. XSetForeground(display, ularn_gc, DkGrey.pixel);
  1198. XFillRectangle(display, ularn_window, ularn_gc,
  1199. MessageLeft, MessageTop - SEPARATOR_HEIGHT + 6,
  1200. MessageWidth, 2);
  1201. //
  1202. // Status area
  1203. //
  1204. XSetForeground(display, ularn_gc, LtGrey.pixel);
  1205. XFillRectangle(display, ularn_window, ularn_gc,
  1206. StatusLeft, StatusTop - SEPARATOR_HEIGHT,
  1207. StatusWidth, 2);
  1208. XSetForeground(display, ularn_gc, MidGrey.pixel);
  1209. XFillRectangle(display, ularn_window, ularn_gc,
  1210. StatusLeft, StatusTop - SEPARATOR_HEIGHT + 2,
  1211. StatusWidth, 4);
  1212. XSetForeground(display, ularn_gc, DkGrey.pixel);
  1213. XFillRectangle(display, ularn_window, ularn_gc,
  1214. StatusLeft, StatusTop - SEPARATOR_HEIGHT + 6,
  1215. StatusWidth, 2);
  1216. //
  1217. // Effects area
  1218. //
  1219. XSetForeground(display, ularn_gc, LtGrey.pixel);
  1220. XFillRectangle(display, ularn_window, ularn_gc,
  1221. EffectsLeft - SEPARATOR_WIDTH, EffectsTop,
  1222. 2, EffectsHeight);
  1223. XSetForeground(display, ularn_gc, MidGrey.pixel);
  1224. XFillRectangle(display, ularn_window, ularn_gc,
  1225. EffectsLeft - SEPARATOR_WIDTH + 2, EffectsTop,
  1226. 4, EffectsHeight + 2);
  1227. XSetForeground(display, ularn_gc, DkGrey.pixel);
  1228. XFillRectangle(display, ularn_window, ularn_gc,
  1229. EffectsLeft - SEPARATOR_WIDTH + 6, EffectsTop,
  1230. 2, EffectsHeight);
  1231. PaintStatus();
  1232. PaintEffects();
  1233. PaintMap();
  1234. PaintTextWindow();
  1235. }
  1236. /* =============================================================================
  1237. * FUNCTION: PaintWindow
  1238. *
  1239. * DESCRIPTION:
  1240. * Repaint the window.
  1241. *
  1242. * PARAMETERS:
  1243. *
  1244. * None.
  1245. *
  1246. * RETURN VALUE:
  1247. *
  1248. * None.
  1249. */
  1250. static void PaintWindow(void)
  1251. {
  1252. Repaint = 1;
  1253. XMENU_Redraw();
  1254. if (CurrentDisplayMode == DISPLAY_MAP)
  1255. {
  1256. PaintMapWindow();
  1257. }
  1258. else
  1259. {
  1260. PaintTextWindow();
  1261. }
  1262. Repaint = 0;
  1263. }
  1264. /* =============================================================================
  1265. * FUNCTION: Resize
  1266. *
  1267. * DESCRIPTION:
  1268. * This procedure handles resizing the window in response to any event that
  1269. * requires the sub-window size and position to be recalculated.
  1270. *
  1271. * PARAMETERS:
  1272. *
  1273. * None.
  1274. *
  1275. * RETURN VALUE:
  1276. *
  1277. * None.
  1278. */
  1279. static void Resize(void)
  1280. {
  1281. XWindowAttributes win_attr;
  1282. int ClientWidth;
  1283. int ClientHeight;
  1284. /* XXX trn - check status rc return val */
  1285. /*Status rc;
  1286. rc = */XGetWindowAttributes(display, ularn_window, &win_attr);
  1287. LarnWindowWidth = win_attr.width;
  1288. LarnWindowHeight = win_attr.height;
  1289. ClientWidth = LarnWindowWidth;
  1290. ClientHeight = LarnWindowHeight;
  1291. //
  1292. // Calculate the message window size and position
  1293. //
  1294. MessageWidth = ClientWidth;
  1295. MessageHeight = CharHeight * MAX_MSG_LINES;
  1296. MessageLeft = 0;
  1297. MessageTop = ClientHeight - MessageHeight - 1;
  1298. //
  1299. // Calculate the Status window size and position
  1300. //
  1301. StatusLeft = 0;
  1302. StatusTop = (MessageTop - SEPARATOR_HEIGHT) - CharHeight * 2;
  1303. StatusWidth = ClientWidth;
  1304. StatusHeight = CharHeight * 2;
  1305. //
  1306. // Calculate the Effects window size and position
  1307. //
  1308. EffectsLeft = ClientWidth - CharWidth * 10;
  1309. EffectsTop = ularn_menu_height;
  1310. EffectsWidth = CharWidth * 10;
  1311. EffectsHeight = StatusTop - SEPARATOR_HEIGHT - EffectsTop;
  1312. //
  1313. // Calculate the size and position of the map window
  1314. //
  1315. MapAreaLeft = 0;
  1316. MapAreaTop = ularn_menu_height;
  1317. MapLeft = 0;
  1318. MapTop = MapAreaTop;
  1319. MapWidth = EffectsLeft - SEPARATOR_WIDTH;
  1320. MapHeight = StatusTop - SEPARATOR_HEIGHT - MapAreaTop;
  1321. MapTileWidth = MapWidth / TileWidth;
  1322. MapTileHeight = MapHeight / TileHeight;
  1323. //
  1324. // Calculate the size and position of the text window
  1325. //
  1326. TextWidth = CharWidth * LINE_LENGTH;
  1327. TextHeight = CharHeight * MAX_TEXT_LINES;
  1328. TextLeft = (ClientWidth - TextWidth) / 2;
  1329. TextTop =
  1330. ularn_menu_height +
  1331. (ClientHeight - TextHeight - ularn_menu_height) / 2;
  1332. //
  1333. // Check if should draw a border around the text page when it is displayed
  1334. //
  1335. ShowTextBorder = (TextLeft >= BORDER_SIZE) &&
  1336. (TextTop >= (ularn_menu_height + BORDER_SIZE));
  1337. //
  1338. // If the map window is bigger than required to display the map, then centre
  1339. // the map in the window.
  1340. //
  1341. if (MapTileWidth > MAXX)
  1342. {
  1343. MapTileWidth = MAXX;
  1344. MapLeft = (MapWidth - MapTileWidth * TileWidth) / 2;
  1345. }
  1346. if (MapTileHeight > MAXY)
  1347. {
  1348. MapTileHeight = MAXY;
  1349. MapTop = MapAreaTop + (MapHeight - MapTileHeight * TileHeight) / 2;
  1350. }
  1351. if (CurrentDisplayMode == DISPLAY_MAP)
  1352. {
  1353. TLeft = MessageLeft;
  1354. TTop = MessageTop;
  1355. TWidth = MessageWidth;
  1356. THeight = MessageHeight;
  1357. }
  1358. else
  1359. {
  1360. TLeft = TextLeft;
  1361. TTop = TextTop;
  1362. TWidth = TextWidth;
  1363. THeight = TextHeight;
  1364. }
  1365. //
  1366. // calculate the map scroll position for the current player position
  1367. //
  1368. calc_scroll();
  1369. //
  1370. // Force the window to redraw
  1371. //
  1372. PaintWindow();
  1373. if (CaretActive)
  1374. {
  1375. XSetForeground(display, ularn_gc, black_pixel);
  1376. XSetClipOrigin(display, ularn_gc,
  1377. TLeft + (CursorX - 1) * CharWidth,
  1378. TTop + (CursorY - 1) * CharHeight + CharAscent);
  1379. XSetClipMask(display, ularn_gc, CursorPixmap);
  1380. XCopyPlane(display, CursorPixmap, ularn_window, ularn_gc,
  1381. 0, 0,
  1382. cursor_width, cursor_height,
  1383. TLeft + (CursorX - 1) * CharWidth,
  1384. TTop + (CursorY - 1) * CharHeight + CharAscent, 1);
  1385. XSetClipOrigin(display, ularn_gc, 0, 0);
  1386. XSetClipMask(display, ularn_gc, None);
  1387. }
  1388. }
  1389. /* =============================================================================
  1390. * FUNCTION: handle_event
  1391. *
  1392. * DESCRIPTION:
  1393. * This procedure handles the processing for X events.
  1394. *
  1395. * PARAMETERS:
  1396. *
  1397. * event : The X event to process.
  1398. *
  1399. * RETURN VALUE:
  1400. *
  1401. * None.
  1402. */
  1403. static void handle_event(XEvent *event)
  1404. {
  1405. int MenuId;
  1406. /* Handle menu input */
  1407. MenuId = XMENU_HandleEvent(event);
  1408. if (MenuId >= 0)
  1409. {
  1410. switch (MenuId)
  1411. {
  1412. case MENU_GAME_SAVE:
  1413. Event = ACTION_SAVE;
  1414. break;
  1415. case MENU_GAME_QUIT:
  1416. Event = ACTION_QUIT;
  1417. break;
  1418. case MENU_ACTION_WAIT:
  1419. Event = ACTION_WAIT;
  1420. break;
  1421. case MENU_ACTION_WIELD:
  1422. Event = ACTION_WIELD;
  1423. break;
  1424. case MENU_ACTION_WEAR:
  1425. Event = ACTION_WEAR;
  1426. break;
  1427. case MENU_ACTION_TAKEOFF:
  1428. Event = ACTION_REMOVE_ARMOUR;
  1429. break;
  1430. case MENU_ACTION_QUAFF:
  1431. Event = ACTION_QUAFF;
  1432. break;
  1433. case MENU_ACTION_READ:
  1434. Event = ACTION_READ;
  1435. break;
  1436. case MENU_ACTION_CAST:
  1437. Event = ACTION_CAST_SPELL;
  1438. break;
  1439. case MENU_ACTION_EAT:
  1440. Event = ACTION_EAT_COOKIE;
  1441. break;
  1442. case MENU_ACTION_DROP:
  1443. Event = ACTION_DROP;
  1444. break;
  1445. case MENU_ACTION_CLOSEDOOR:
  1446. Event = ACTION_CLOSE_DOOR;
  1447. break;
  1448. case MENU_SHOW_DISCOVERIES:
  1449. Event = ACTION_LIST_SPELLS;
  1450. break;
  1451. case MENU_SHOW_INVENTORY:
  1452. Event = ACTION_INVENTORY;
  1453. break;
  1454. case MENU_SHOW_TAX:
  1455. Event = ACTION_SHOW_TAX;
  1456. break;
  1457. case MENU_SHOW_PACKWEIGHT:
  1458. Event = ACTION_PACK_WEIGHT;
  1459. break;
  1460. case MENU_DISPLAY_REDRAW:
  1461. Event = ACTION_REDRAW_SCREEN;
  1462. break;
  1463. case MENU_DISPLAY_BEEP:
  1464. nobeep = !nobeep;
  1465. /* Set menu checkmarks */
  1466. if (nobeep)
  1467. {
  1468. XMENU_SetCheck(MENU_DISPLAY_BEEP, XMENU_UNCHECKED);
  1469. }
  1470. else
  1471. {
  1472. XMENU_SetCheck(MENU_DISPLAY_BEEP, XMENU_CHECKED);
  1473. }
  1474. break;
  1475. case MENU_DISPLAY_FONT:
  1476. break;
  1477. case MENU_HELP_HELP:
  1478. Event = ACTION_HELP;
  1479. break;
  1480. case MENU_HELP_VERSION:
  1481. Event = ACTION_VERSION;
  1482. break;
  1483. case MENU_HELP_ABOUT:
  1484. break;
  1485. default:
  1486. break;
  1487. }
  1488. return;
  1489. }
  1490. //
  1491. // What is the message
  1492. //
  1493. switch (event->type)
  1494. {
  1495. case Expose:
  1496. if (event->xexpose.count == 0)
  1497. {
  1498. PaintWindow();
  1499. }
  1500. break;
  1501. case ConfigureNotify:
  1502. Resize();
  1503. break;
  1504. case KeyPress:
  1505. {
  1506. ActionType Action;
  1507. int ModKey = 0;
  1508. int Found = 0;
  1509. KeySym key_symbol;
  1510. XComposeStatus compose;
  1511. char KeyString[40];
  1512. int i;
  1513. XLookupString(&(event->xkey), KeyString, 40, &key_symbol, &compose);
  1514. if ((event->xkey.state & ShiftMask) != 0)
  1515. {
  1516. ModKey |= M_SHIFT;
  1517. }
  1518. if ((event->xkey.state & ControlMask) != 0)
  1519. {
  1520. ModKey |= M_CTRL;
  1521. }
  1522. /* Get ASCII character */
  1523. EventChar = KeyString[0];
  1524. GotChar = (EventChar != 0);
  1525. /* Decode key press as a ULarn Action */
  1526. Action = ACTION_NULL;
  1527. /* Check virtual key bindings */
  1528. while ((Action < ACTION_COUNT) && (!Found))
  1529. {
  1530. for (i = 0 ; i < MAX_KEY_BINDINGS ; i++)
  1531. {
  1532. if (KeyMap[Action][i].ModKey != M_ASCII)
  1533. {
  1534. /* Virtual key binding */
  1535. if ((key_symbol == KeyMap[Action][i].VirtKey) &&
  1536. (KeyMap[Action][i].ModKey == ModKey))
  1537. {
  1538. Found = 1;
  1539. }
  1540. }
  1541. }
  1542. if (!Found)
  1543. {
  1544. Action++;
  1545. }
  1546. }
  1547. /*
  1548. * Check ASCII key bindings if no virtual key matches and
  1549. * got a valid ASCII char
  1550. */
  1551. if (!Found && GotChar)
  1552. {
  1553. Action = ACTION_NULL;
  1554. while ((Action < ACTION_COUNT) && (!Found))
  1555. {
  1556. for (i = 0 ; i < MAX_KEY_BINDINGS ; i++)
  1557. {
  1558. if (KeyMap[Action][i].ModKey == M_ASCII)
  1559. {
  1560. /* ASCII key binding */
  1561. if (EventChar == KeyMap[Action][i].VirtKey)
  1562. {
  1563. Found = 1;
  1564. }
  1565. }
  1566. }
  1567. if (!Found)
  1568. {
  1569. Action++;
  1570. }
  1571. }
  1572. }
  1573. if (Found)
  1574. {
  1575. Event = Action;
  1576. }
  1577. else
  1578. {
  1579. /* check run key */
  1580. if ((key_symbol == RunKeyMap.VirtKey) &&
  1581. (RunKeyMap.ModKey == ModKey))
  1582. {
  1583. Runkey = 1;
  1584. }
  1585. }
  1586. break;
  1587. }
  1588. default:
  1589. break;
  1590. }
  1591. }
  1592. #define MASK_TILES 9
  1593. static int MaskTiles[MASK_TILES][2] =
  1594. {
  1595. { 240, 248 },
  1596. { 241, 249 },
  1597. { 242, 250 },
  1598. { 243, 251 },
  1599. { 244, 252 },
  1600. { 245, 253 },
  1601. { 246, 254 },
  1602. { 247, 255 },
  1603. { TILE_CURSOR1, TILE_CURSOR2 }
  1604. };
  1605. /* =============================================================================
  1606. * FUNCTION: MakeTileMasks
  1607. *
  1608. * DESCRIPTION:
  1609. * This procedure makes the transparency masks for overlay tiles.
  1610. *
  1611. * PARAMETERS:
  1612. *
  1613. * None.
  1614. *
  1615. * RETURN VALUE:
  1616. *
  1617. * None.
  1618. */
  1619. void MakeTileMasks(void)
  1620. {
  1621. XImage *Image1;
  1622. XImage *Image2;
  1623. XImage *Mask;
  1624. GC gc;
  1625. XGCValues values;
  1626. int Tile;
  1627. int x, y;
  1628. int t1x, t1y;
  1629. int t2x, t2y;
  1630. int p1, p2;
  1631. if (TilePShape == None)
  1632. {
  1633. printf("TilePShape not allocated!\n");
  1634. }
  1635. values.foreground = 1;
  1636. values.background = 0;
  1637. gc = XCreateGC(display, TilePShape, GCForeground | GCBackground, &values);
  1638. for (Tile = 0 ; Tile < MASK_TILES ; Tile++)
  1639. {
  1640. t1x = (MaskTiles[Tile][0] % 16) * TileWidth;
  1641. t1y = (MaskTiles[Tile][0] / 16) * TileHeight;
  1642. t2x = (MaskTiles[Tile][1] % 16) * TileWidth;
  1643. t2y = (MaskTiles[Tile][1] / 16) * TileHeight;
  1644. Image1 = XGetImage(display, TilePixmap, t1x, t1y, TileWidth, TileHeight, 0xffffffff, XYPixmap);
  1645. Image2 = XGetImage(display, TilePixmap, t2x, t2y, TileWidth, TileHeight, 0xffffffff, XYPixmap);
  1646. Mask = XGetImage(display, TilePShape, t1x, t1y, TileWidth, TileHeight, 0xffffffff, XYPixmap);
  1647. for (y = 0 ; y < TileHeight ; y++)
  1648. {
  1649. for (x = 0 ; x < TileWidth ; x++)
  1650. {
  1651. p1 = XGetPixel(Image1, x, y);
  1652. p2 = XGetPixel(Image2, x, y);
  1653. if (p1 != p2)
  1654. {
  1655. XPutPixel(Mask, x, y, 0);
  1656. }
  1657. else
  1658. {
  1659. XPutPixel(Mask, x, y, 1);
  1660. }
  1661. }
  1662. XPutImage(display, TilePShape, gc, Mask, 0, 0, t1x, t1y, TileWidth, TileHeight);
  1663. }
  1664. }
  1665. XFreeGC(display, gc);
  1666. }
  1667. /* =============================================================================
  1668. * Exported functions
  1669. */
  1670. /* =============================================================================
  1671. * FUNCTION: init_app
  1672. */
  1673. int init_app(char *DisplayName)
  1674. {
  1675. int x, y;
  1676. /* XXX trn */
  1677. /*Visual *visual;*/
  1678. int rc;
  1679. char *LoadingText = "Loading data...";
  1680. char *UlarnText = "VLarn";
  1681. XTextProperty xtext;
  1682. display = XOpenDisplay(DisplayName);
  1683. if (display == NULL)
  1684. {
  1685. fprintf(stderr, "Error: Cannot connect to X server %s\n", DisplayName);
  1686. /*return 0;*/
  1687. exit(1);
  1688. }
  1689. screen_num = DefaultScreen(display);
  1690. white_pixel = WhitePixel(display, screen_num);
  1691. black_pixel = BlackPixel(display, screen_num);
  1692. screen_width = DisplayWidth(display, screen_num);
  1693. screen_height = DisplayHeight(display, screen_num);
  1694. root_window = RootWindow(display, screen_num);
  1695. ularn_window = XCreateSimpleWindow(
  1696. display,
  1697. root_window,
  1698. 10, 10,
  1699. INITIAL_WIDTH, INITIAL_HEIGHT,
  1700. 2,
  1701. BlackPixel(display, screen_num), WhitePixel(display, screen_num));
  1702. /* Set the window name */
  1703. if (XStringListToTextProperty(&LoadingText, 1, &xtext) == 0)
  1704. {
  1705. printf("XStringListToTextProperty ran out of memory\n");
  1706. return 0;
  1707. }
  1708. XSetWMName(display, ularn_window, &xtext);
  1709. XFree(xtext.value);
  1710. XMapWindow(display, ularn_window);
  1711. XFlush(display);
  1712. XSync(display, 0);
  1713. /* Create the graphics context */
  1714. gc_values.cap_style = CapButt;
  1715. gc_values.join_style = JoinBevel;
  1716. gc_values_mask = GCCapStyle | GCJoinStyle;
  1717. ularn_gc = XCreateGC(display, ularn_window, gc_values_mask, &gc_values);
  1718. /*
  1719. * Install the menu and set initial check states
  1720. */
  1721. XMENU_SetMenu(display, ularn_window, &Game_Menu, NULL, PaintWindow);
  1722. ularn_menu_height = XMENU_GetMenuHeight();
  1723. if (nobeep)
  1724. {
  1725. XMENU_SetCheck(MENU_DISPLAY_BEEP, XMENU_UNCHECKED);
  1726. }
  1727. else
  1728. {
  1729. XMENU_SetCheck(MENU_DISPLAY_BEEP, XMENU_CHECKED);
  1730. }
  1731. /* Get colours required */
  1732. /*visual = */DefaultVisual(display, DefaultScreen(display));
  1733. colormap = XDefaultColormap(display, screen_num);
  1734. LtGrey.red = 192 * 256;
  1735. LtGrey.green = 192 * 256;
  1736. LtGrey.blue = 192 * 256;
  1737. XAllocColor(display, colormap, &LtGrey);
  1738. MidGrey.red = 128 * 256;
  1739. MidGrey.green = 128 * 256;
  1740. MidGrey.blue = 128 * 256;
  1741. XAllocColor(display, colormap, &MidGrey);
  1742. DkGrey.red = 96 * 256;
  1743. DkGrey.green = 96 * 256;
  1744. DkGrey.blue = 96 * 256;
  1745. XAllocColor(display, colormap, &DkGrey);
  1746. Red.red = 255 * 256;
  1747. Red.green = 0;
  1748. Red.blue = 0;
  1749. XAllocColor(display, colormap, &Red);
  1750. Green.red = 0;
  1751. Green.green = 128 * 256;
  1752. Green.blue = 0;
  1753. XAllocColor(display, colormap, &Green);
  1754. Blue.red = 0;
  1755. Blue.green = 0;
  1756. Blue.blue = 255 * 256;
  1757. XAllocColor(display, colormap, &Blue);
  1758. font_info = XLoadQueryFont(display, font_name);
  1759. if (!font_info)
  1760. {
  1761. fprintf(stderr, "Error: XLoadQueryFont: failed loading font '%s'\n", font_name);
  1762. return 0;
  1763. }
  1764. XSetFont(display, ularn_gc, font_info->fid);
  1765. XSelectInput(
  1766. display,
  1767. ularn_window,
  1768. ExposureMask | KeyPressMask | StructureNotifyMask | XMENU_EVENT_MASK);
  1769. CursorPixmap = XCreateBitmapFromData(display, ularn_window,
  1770. cursor_bits, cursor_width, cursor_height);
  1771. TileAttributes.valuemask = XpmCloseness;
  1772. TileAttributes.closeness = 25000;
  1773. rc = XpmReadFileToPixmap(display,
  1774. ularn_window,
  1775. TileFilename,
  1776. &TilePixmap,
  1777. &TilePShape,
  1778. &TileAttributes);
  1779. if (rc < XpmSuccess)
  1780. {
  1781. printf("Error reading pixmap: %s\n", XpmGetErrorString(rc));
  1782. printf("Retrying with inferior colours\n");
  1783. TileAttributes.valuemask = XpmCloseness;
  1784. TileAttributes.closeness = 50000;
  1785. rc = XpmReadFileToPixmap(display,
  1786. ularn_window,
  1787. TileFilename,
  1788. &TilePixmap,
  1789. &TilePShape,
  1790. &TileAttributes);
  1791. if (rc < XpmSuccess)
  1792. {
  1793. printf("Error reading pixmap: %s\n", XpmGetErrorString(rc));
  1794. }
  1795. }
  1796. MakeTileMasks();
  1797. //
  1798. // Clear the text buffers
  1799. //
  1800. for (y = 0 ; y < MAX_MSG_LINES ; y++)
  1801. {
  1802. for (x = 0 ; x < LINE_LENGTH ; x++)
  1803. {
  1804. MessageChr[y][x] = ' ';
  1805. MessageFmt[y][x] = FORMAT_NORMAL;
  1806. }
  1807. MessageChr[y][LINE_LENGTH] = 0;
  1808. }
  1809. for (y = 0 ; y < MAX_TEXT_LINES ; y++)
  1810. {
  1811. for (x = 0 ; x < LINE_LENGTH ; x++)
  1812. {
  1813. TextChr[y][x] = ' ';
  1814. TextFmt[y][x] = FORMAT_NORMAL;
  1815. }
  1816. TextChr[y][LINE_LENGTH] = 0;
  1817. }
  1818. if (XStringListToTextProperty(&UlarnText, 1, &xtext) == 0)
  1819. {
  1820. printf("XStringListToTextProperty ran out of memory\n");
  1821. return 0;
  1822. }
  1823. XSetWMName(display, ularn_window, &xtext);
  1824. XFree(xtext.value);
  1825. //
  1826. // Set the initial window size
  1827. //
  1828. CalcMinWindowSize();
  1829. Resize();
  1830. return 1;
  1831. }
  1832. /* =============================================================================
  1833. * FUNCTION: close_app
  1834. */
  1835. void close_app(void)
  1836. {
  1837. if (TilePixmap != None)
  1838. {
  1839. XFreePixmap(display, TilePixmap);
  1840. }
  1841. if (TilePShape != None)
  1842. {
  1843. XFreePixmap(display, TilePShape);
  1844. }
  1845. if (CursorPixmap != None)
  1846. {
  1847. XFreePixmap(display, CursorPixmap);
  1848. }
  1849. if (ularn_gc != None)
  1850. {
  1851. XFreeColormap(display, colormap);
  1852. XFreeGC(display, ularn_gc);
  1853. }
  1854. if (ularn_window != None)
  1855. {
  1856. XDestroyWindow(display, ularn_window);
  1857. }
  1858. sleep(4);
  1859. XFlush(display);
  1860. XSync(display, 1);
  1861. if (display != NULL)
  1862. {
  1863. XCloseDisplay(display);
  1864. }
  1865. }
  1866. /* =============================================================================
  1867. * FUNCTION: get_normal_input
  1868. */
  1869. ActionType get_normal_input(void)
  1870. {
  1871. XEvent xevent; // The X event
  1872. int idx;
  1873. int got_dir;
  1874. Event = ACTION_NULL;
  1875. Runkey = 0;
  1876. while (Event == ACTION_NULL)
  1877. {
  1878. XNextEvent(display, &xevent);
  1879. handle_event(&xevent);
  1880. //
  1881. // Clear enhanced interface events in enhanced interface is not active
  1882. //
  1883. if (!enhance_interface)
  1884. {
  1885. if ((Event == ACTION_OPEN_DOOR) ||
  1886. (Event == ACTION_OPEN_CHEST))
  1887. {
  1888. Event = ACTION_NULL;
  1889. }
  1890. }
  1891. }
  1892. if (Runkey)
  1893. {
  1894. idx = 0;
  1895. got_dir = 0;
  1896. while ((idx < NUM_DIRS) && (!got_dir))
  1897. {
  1898. if (DirActions[idx] == Event)
  1899. {
  1900. got_dir = 1;
  1901. }
  1902. else
  1903. {
  1904. idx++;
  1905. }
  1906. }
  1907. if (got_dir)
  1908. {
  1909. /* modify into a run event */
  1910. Event = Event + 1;
  1911. }
  1912. }
  1913. return Event;
  1914. }
  1915. /* =============================================================================
  1916. * FUNCTION: get_prompt_input
  1917. */
  1918. char get_prompt_input(char *prompt, char *answers, int ShowCursor)
  1919. {
  1920. XEvent xevent; // The X event
  1921. char *ch;
  1922. Print(prompt);
  1923. if (ShowCursor)
  1924. {
  1925. XSetForeground(display, ularn_gc, black_pixel);
  1926. XSetClipOrigin(display, ularn_gc,
  1927. TLeft + (CursorX - 1) * CharWidth,
  1928. TTop + (CursorY - 1) * CharHeight + CharAscent);
  1929. XSetClipMask(display, ularn_gc, CursorPixmap);
  1930. XCopyPlane(display, CursorPixmap, ularn_window, ularn_gc,
  1931. 0, 0,
  1932. cursor_width, cursor_height,
  1933. TLeft + (CursorX - 1) * CharWidth,
  1934. TTop + (CursorY - 1) * CharHeight + CharAscent, 1);
  1935. XSetClipOrigin(display, ularn_gc, 0, 0);
  1936. XSetClipMask(display, ularn_gc, None);
  1937. CaretActive = 1;
  1938. }
  1939. //
  1940. // Process events until a character in answers has been pressed.
  1941. //
  1942. GotChar = 0;
  1943. while (!GotChar)
  1944. {
  1945. XNextEvent(display, &xevent);
  1946. handle_event(&xevent);
  1947. if (GotChar)
  1948. {
  1949. //
  1950. // Search for the input character in the answers string
  1951. //
  1952. ch = strchr(answers, EventChar);
  1953. if (ch == NULL)
  1954. {
  1955. //
  1956. // Not an answer we want
  1957. //
  1958. GotChar = 0;
  1959. }
  1960. }
  1961. }
  1962. if (ShowCursor)
  1963. {
  1964. XSetForeground(display, ularn_gc, white_pixel);
  1965. XSetClipOrigin(display, ularn_gc,
  1966. TLeft + (CursorX - 1) * CharWidth,
  1967. TTop + (CursorY - 1) * CharHeight + CharAscent);
  1968. XSetClipMask(display, ularn_gc, CursorPixmap);
  1969. XCopyPlane(display, CursorPixmap, ularn_window, ularn_gc,
  1970. 0, 0,
  1971. cursor_width, cursor_height,
  1972. TLeft + (CursorX - 1) * CharWidth,
  1973. TTop + (CursorY - 1) * CharHeight + CharAscent, 1);
  1974. XSetClipOrigin(display, ularn_gc, 0, 0);
  1975. XSetClipMask(display, ularn_gc, None);
  1976. CaretActive = 0;
  1977. }
  1978. return EventChar;
  1979. }
  1980. /* =============================================================================
  1981. * FUNCTION: get_password_input
  1982. */
  1983. void get_password_input(char *password, int Len)
  1984. {
  1985. char ch;
  1986. char inputchars[256];
  1987. int Pos;
  1988. int value;
  1989. /* get the printable characters on this system */
  1990. Pos = 0;
  1991. for (value = 0 ; value < 256 ; value++)
  1992. {
  1993. if (isprint(value))
  1994. {
  1995. inputchars[Pos] = (char) value;
  1996. Pos++;
  1997. }
  1998. }
  1999. /* add CR, BS and null terminator */
  2000. inputchars[Pos++] = '\010';
  2001. inputchars[Pos++] = '\015';
  2002. inputchars[Pos] = '\0';
  2003. Pos = 0;
  2004. do
  2005. {
  2006. ch = get_prompt_input("", inputchars, 1);
  2007. if (isprint((int) ch) && (Pos < Len))
  2008. {
  2009. password[Pos] = ch;
  2010. Pos++;
  2011. Printc('*');
  2012. }
  2013. else if (ch == '\010')
  2014. {
  2015. //
  2016. // Backspace
  2017. //
  2018. if (Pos > 0)
  2019. {
  2020. CursorX--;
  2021. Printc(' ');
  2022. CursorX--;
  2023. Pos--;
  2024. }
  2025. }
  2026. } while (ch != '\015');
  2027. password[Pos] = 0;
  2028. }
  2029. /* =============================================================================
  2030. * FUNCTION: get_num_input
  2031. */
  2032. int get_num_input(int defval)
  2033. {
  2034. char ch;
  2035. int Pos = 0;
  2036. int value = 0;
  2037. int neg = 0;
  2038. do
  2039. {
  2040. ch = get_prompt_input("", "-*0123456789\010\015", 1);
  2041. if ((ch == '-') && (Pos == 0))
  2042. {
  2043. //
  2044. // Minus
  2045. //
  2046. neg = 1;
  2047. Printc(ch);
  2048. Pos++;
  2049. }
  2050. if (ch == '*')
  2051. {
  2052. return defval;
  2053. }
  2054. else if (ch == '\010')
  2055. {
  2056. //
  2057. // Backspace
  2058. //
  2059. if (Pos > 0)
  2060. {
  2061. if ((Pos == 1) && neg)
  2062. {
  2063. neg = 0;
  2064. }
  2065. else
  2066. {
  2067. value = value / 10;
  2068. }
  2069. CursorX--;
  2070. Printc(' ');
  2071. CursorX--;
  2072. Pos--;
  2073. }
  2074. }
  2075. else if ((ch >= '0') && (ch <= '9'))
  2076. {
  2077. //
  2078. // digit
  2079. //
  2080. value = value * 10 + (ch - '0');
  2081. Printc(ch);
  2082. Pos++;
  2083. }
  2084. } while (ch != '\015');
  2085. if (Pos == 0)
  2086. {
  2087. return defval;
  2088. }
  2089. else
  2090. {
  2091. if (neg) value = -value;
  2092. return value;
  2093. }
  2094. }
  2095. /* =============================================================================
  2096. * FUNCTION: get_dir_input
  2097. */
  2098. ActionType get_dir_input(char *prompt, int ShowCursor)
  2099. {
  2100. XEvent xevent;
  2101. int got_dir;
  2102. int idx;
  2103. //
  2104. // Display the prompt at the current position
  2105. //
  2106. Print(prompt);
  2107. //
  2108. // Show the cursor if required
  2109. //
  2110. if (ShowCursor)
  2111. {
  2112. XSetForeground(display, ularn_gc, black_pixel);
  2113. XSetClipOrigin(display, ularn_gc,
  2114. TLeft + (CursorX - 1) * CharWidth,
  2115. TTop + (CursorY - 1) * CharHeight + CharAscent);
  2116. XSetClipMask(display, ularn_gc, CursorPixmap);
  2117. XCopyPlane(display, CursorPixmap, ularn_window, ularn_gc,
  2118. 0, 0,
  2119. cursor_width, cursor_height,
  2120. TLeft + (CursorX - 1) * CharWidth,
  2121. TTop + (CursorY - 1) * CharHeight + CharAscent, 1);
  2122. XSetClipOrigin(display, ularn_gc, 0, 0);
  2123. XSetClipMask(display, ularn_gc, None);
  2124. CaretActive = 1;
  2125. }
  2126. Event = ACTION_NULL;
  2127. got_dir = 0;
  2128. while (!got_dir)
  2129. {
  2130. XNextEvent(display, &xevent);
  2131. handle_event(&xevent);
  2132. idx = 0;
  2133. while ((idx < NUM_DIRS) && (!got_dir))
  2134. {
  2135. if (DirActions[idx] == Event)
  2136. {
  2137. got_dir = 1;
  2138. }
  2139. else
  2140. {
  2141. idx++;
  2142. }
  2143. }
  2144. }
  2145. if (ShowCursor)
  2146. {
  2147. XSetForeground(display, ularn_gc, white_pixel);
  2148. XSetClipOrigin(display, ularn_gc,
  2149. TLeft + (CursorX - 1) * CharWidth,
  2150. TTop + (CursorY - 1) * CharHeight + CharAscent);
  2151. XSetClipMask(display, ularn_gc, CursorPixmap);
  2152. XCopyPlane(display, CursorPixmap, ularn_window, ularn_gc,
  2153. 0, 0,
  2154. cursor_width, cursor_height,
  2155. TLeft + (CursorX - 1) * CharWidth,
  2156. TTop + (CursorY - 1) * CharHeight + CharAscent, 1);
  2157. XSetClipOrigin(display, ularn_gc, 0, 0);
  2158. XSetClipMask(display, ularn_gc, None);
  2159. CaretActive = 0;
  2160. }
  2161. return Event;
  2162. }
  2163. /* =============================================================================
  2164. * FUNCTION: UpdateStatus
  2165. */
  2166. void UpdateStatus(void)
  2167. {
  2168. if (CurrentDisplayMode == DISPLAY_TEXT)
  2169. {
  2170. /* Don't redisplay if in text mode */
  2171. return;
  2172. }
  2173. PaintStatus();
  2174. }
  2175. /* =============================================================================
  2176. * FUNCTION: UpdateEffects
  2177. */
  2178. void UpdateEffects(void)
  2179. {
  2180. if (CurrentDisplayMode == DISPLAY_TEXT)
  2181. {
  2182. /* Don't redisplay if in text mode */
  2183. return;
  2184. }
  2185. PaintEffects();
  2186. }
  2187. /* =============================================================================
  2188. * FUNCTION: UpdateStatusAndEffects
  2189. */
  2190. void UpdateStatusAndEffects(void)
  2191. {
  2192. if (CurrentDisplayMode == DISPLAY_TEXT)
  2193. {
  2194. /* Don't redisplay if in text mode */
  2195. return;
  2196. }
  2197. //
  2198. // Do effects first as update status will mark all effects as current
  2199. //
  2200. PaintEffects();
  2201. PaintStatus();
  2202. }
  2203. /* =============================================================================
  2204. * FUNCTION: set_display
  2205. */
  2206. void set_display(DisplayModeType Mode)
  2207. {
  2208. //
  2209. // Save the current settings
  2210. //
  2211. if (CurrentDisplayMode == DISPLAY_MAP)
  2212. {
  2213. MsgCursorX = CursorX;
  2214. MsgCursorY = CursorY;
  2215. CurrentMsgFormat = CurrentFormat;
  2216. }
  2217. else if (CurrentDisplayMode == DISPLAY_TEXT)
  2218. {
  2219. TextCursorX = CursorX;
  2220. TextCursorY = CursorY;
  2221. CurrentTextFormat = CurrentFormat;
  2222. }
  2223. CurrentDisplayMode = Mode;
  2224. //
  2225. // Set the text buffer settings for the new display mode
  2226. //
  2227. if (CurrentDisplayMode == DISPLAY_MAP)
  2228. {
  2229. CursorX = MsgCursorX;
  2230. CursorY = MsgCursorY;
  2231. CurrentFormat = CurrentMsgFormat;
  2232. Text = MessageChr;
  2233. Format = MessageFmt;
  2234. MaxLine = MAX_MSG_LINES;
  2235. TLeft = MessageLeft;
  2236. TTop = MessageTop;
  2237. TWidth = MessageWidth;
  2238. THeight = MessageHeight;
  2239. }
  2240. else if (CurrentDisplayMode == DISPLAY_TEXT)
  2241. {
  2242. CursorX = TextCursorX;
  2243. CursorY = TextCursorY;
  2244. CurrentFormat = CurrentTextFormat;
  2245. Text = TextChr;
  2246. Format = TextFmt;
  2247. MaxLine = MAX_TEXT_LINES;
  2248. TLeft = TextLeft;
  2249. TTop = TextTop;
  2250. TWidth = TextWidth;
  2251. THeight = TextHeight;
  2252. }
  2253. PaintWindow();
  2254. }
  2255. /* =============================================================================
  2256. * FUNCTION: IncCursorY
  2257. *
  2258. * DESCRIPTION:
  2259. * Increae the cursor y position, scrolling the text window if requried.
  2260. *
  2261. * PARAMETERS:
  2262. *
  2263. * Count : The number of lines to increase the cursor y position
  2264. *
  2265. * RETURN VALUE:
  2266. *
  2267. * None.
  2268. */
  2269. static void IncCursorY(int Count)
  2270. {
  2271. int Scroll;
  2272. int inc;
  2273. int Line;
  2274. int x;
  2275. inc = Count;
  2276. Scroll = 0;
  2277. while (inc > 0)
  2278. {
  2279. CursorY = CursorY + 1;
  2280. if (CursorY > MaxLine)
  2281. {
  2282. Scroll = 1;
  2283. for (Line = 0 ; Line < (MaxLine - 1) ; Line++)
  2284. {
  2285. for (x = 0 ; x < LINE_LENGTH ; x++)
  2286. {
  2287. Text[Line][x] = Text[Line+1][x];
  2288. Format[Line][x] = Format[Line+1][x];
  2289. }
  2290. }
  2291. CursorY--;
  2292. for (x = 0 ; x < LINE_LENGTH ; x++)
  2293. {
  2294. Text[MaxLine-1][x] = ' ';
  2295. Format[MaxLine-1][x] = FORMAT_NORMAL;
  2296. }
  2297. }
  2298. inc--;
  2299. }
  2300. if (Scroll)
  2301. {
  2302. PaintTextWindow();
  2303. }
  2304. }
  2305. /* =============================================================================
  2306. * FUNCTION: IncCursorX
  2307. *
  2308. * DESCRIPTION:
  2309. * Increase the cursor x position, handling line wrap.
  2310. *
  2311. * PARAMETERS:
  2312. *
  2313. * Count : The amount to increase the cursor x position.
  2314. *
  2315. * RETURN VALUE:
  2316. *
  2317. * None.
  2318. */
  2319. static void IncCursorX(int Count)
  2320. {
  2321. CursorX = CursorX + Count;
  2322. if (CursorX > LINE_LENGTH)
  2323. {
  2324. CursorX = 1;
  2325. IncCursorY(1);
  2326. }
  2327. }
  2328. /* =============================================================================
  2329. * FUNCTION: ClearText
  2330. */
  2331. void ClearText(void)
  2332. {
  2333. int x, y;
  2334. //
  2335. // Clear the text buffer
  2336. //
  2337. for (y = 0 ; y < MaxLine ; y++)
  2338. {
  2339. for (x = 0 ; x < LINE_LENGTH ; x++)
  2340. {
  2341. Text[y][x] = ' ';
  2342. Format[y][x] = FORMAT_NORMAL;
  2343. }
  2344. Text[y][LINE_LENGTH] = 0;
  2345. }
  2346. CursorX = 1;
  2347. CursorY = 1;
  2348. //
  2349. // Clear the text area
  2350. //
  2351. PaintTextWindow();
  2352. XFlush(display);
  2353. XSync(display, 0);
  2354. }
  2355. /* =============================================================================
  2356. * FUNCTION: UlarnBeep
  2357. */
  2358. void UlarnBeep(void)
  2359. {
  2360. //
  2361. // Middle C, 1/4 second
  2362. //
  2363. if (!nobeep)
  2364. {
  2365. XBell(display, 100);
  2366. }
  2367. }
  2368. /* =============================================================================
  2369. * FUNCTION: Cursor
  2370. */
  2371. void MoveCursor(int x, int y)
  2372. {
  2373. CursorX = x;
  2374. CursorY = y;
  2375. }
  2376. /* =============================================================================
  2377. * FUNCTION: Printc
  2378. */
  2379. void Printc(char c)
  2380. {
  2381. int incx;
  2382. char lc;
  2383. switch (c)
  2384. {
  2385. case '\t':
  2386. incx = ((((CursorX - 1) / 8) + 1) * 8 + 1) - CursorX;
  2387. IncCursorX(incx);
  2388. break;
  2389. case '\n':
  2390. CursorX = 1;
  2391. IncCursorY(1);
  2392. break;
  2393. case '\015':
  2394. break;
  2395. default:
  2396. lc = Text[CursorY-1][CursorX-1];
  2397. if (lc != c)
  2398. {
  2399. /* Erase the char that was here */
  2400. XSetForeground(display, ularn_gc, white_pixel);
  2401. XSetBackground(display, ularn_gc, black_pixel);
  2402. XSetFillStyle(display, ularn_gc, FillSolid);
  2403. XFillRectangle(display, ularn_window, ularn_gc,
  2404. TLeft + (CursorX - 1) * CharWidth,
  2405. TTop + (CursorY - 1) * CharHeight,
  2406. CharWidth, CharHeight);
  2407. }
  2408. Text[CursorY-1][CursorX-1] = c;
  2409. Format[CursorY-1][CursorX-1] = CurrentFormat;
  2410. switch (CurrentFormat)
  2411. {
  2412. case FORMAT_NORMAL:
  2413. XSetForeground(display, ularn_gc, black_pixel);
  2414. break;
  2415. case FORMAT_STANDOUT:
  2416. XSetForeground(display, ularn_gc, Red.pixel);
  2417. break;
  2418. case FORMAT_STANDOUT2:
  2419. XSetForeground(display, ularn_gc, Green.pixel);
  2420. break;
  2421. case FORMAT_STANDOUT3:
  2422. XSetForeground(display, ularn_gc, Blue.pixel);
  2423. break;
  2424. default:
  2425. break;
  2426. }
  2427. XDrawString(display, ularn_window, ularn_gc,
  2428. TLeft + (CursorX - 1) * CharWidth,
  2429. TTop + (CursorY - 1) * CharHeight + CharAscent,
  2430. &c, 1);
  2431. IncCursorX(1);
  2432. break;
  2433. }
  2434. }
  2435. /* =============================================================================
  2436. * FUNCTION: Print
  2437. */
  2438. void Print(char *string)
  2439. {
  2440. int Len;
  2441. int pos;
  2442. if (string == NULL) return;
  2443. Len = strlen(string);
  2444. if (Len == 0) return;
  2445. for (pos = 0 ; pos < Len ; pos++)
  2446. {
  2447. Printc(string[pos]);
  2448. }
  2449. XFlush(display);
  2450. XSync(display, 0);
  2451. }
  2452. /* =============================================================================
  2453. * FUNCTION: Printf
  2454. */
  2455. void Printf(char *fmt, ...)
  2456. {
  2457. char buf[2048];
  2458. va_list argptr;
  2459. va_start(argptr, fmt);
  2460. vsprintf(buf, fmt, argptr);
  2461. va_end(argptr);
  2462. Print(buf);
  2463. }
  2464. /* =============================================================================
  2465. * FUNCTION: Standout
  2466. */
  2467. void Standout(char *String)
  2468. {
  2469. CurrentFormat = FORMAT_STANDOUT;
  2470. Print(String);
  2471. CurrentFormat = FORMAT_NORMAL;
  2472. }
  2473. /* =============================================================================
  2474. * FUNCTION: SetFormat
  2475. */
  2476. void SetFormat(FormatType format)
  2477. {
  2478. CurrentFormat = format;
  2479. }
  2480. /* =============================================================================
  2481. * FUNCTION: ClearToEOL
  2482. */
  2483. void ClearToEOL(void)
  2484. {
  2485. int x;
  2486. for (x = CursorX ; x <= LINE_LENGTH ; x++)
  2487. {
  2488. Text[CursorY-1][x-1] = ' ';
  2489. Format[CursorY-1][x-1] = FORMAT_NORMAL;
  2490. }
  2491. XSetForeground(display, ularn_gc, white_pixel);
  2492. XSetBackground(display, ularn_gc, black_pixel);
  2493. XSetFillStyle(display, ularn_gc, FillSolid);
  2494. XFillRectangle(display, ularn_window, ularn_gc,
  2495. TLeft + (CursorX - 1) * CharWidth,
  2496. TTop + (CursorY - 1) * CharHeight,
  2497. ((LINE_LENGTH - CursorX) + 1) * CharWidth,
  2498. CharHeight);
  2499. }
  2500. /* =============================================================================
  2501. * FUNCTION: ClearToEOPage
  2502. */
  2503. void ClearToEOPage(int x, int y)
  2504. {
  2505. int tx, ty;
  2506. for (tx = x ; tx <= LINE_LENGTH ; tx++)
  2507. {
  2508. Text[y-1][tx-1] = ' ';
  2509. Format[y-1][tx-1] = FORMAT_NORMAL;
  2510. }
  2511. XSetForeground(display, ularn_gc, white_pixel);
  2512. XSetBackground(display, ularn_gc, black_pixel);
  2513. XSetFillStyle(display, ularn_gc, FillSolid);
  2514. XFillRectangle(display, ularn_window, ularn_gc,
  2515. TLeft + (x - 1) * CharWidth,
  2516. TTop + (y - 1) * CharHeight,
  2517. ((LINE_LENGTH - x) + 1) * CharWidth,
  2518. CharHeight);
  2519. for (ty = y+1 ; ty <= MaxLine ; ty++)
  2520. {
  2521. for (tx = 1 ; tx <= LINE_LENGTH ; tx++)
  2522. {
  2523. Text[ty-1][tx-1] = ' ';
  2524. Format[ty-1][tx-1] = FORMAT_NORMAL;
  2525. }
  2526. XFillRectangle(display, ularn_window, ularn_gc,
  2527. TLeft,
  2528. TTop + (ty - 1) * CharHeight,
  2529. LINE_LENGTH * CharWidth,
  2530. CharHeight);
  2531. }
  2532. }
  2533. /* =============================================================================
  2534. * FUNCTION: show1cell
  2535. */
  2536. void show1cell(int x, int y)
  2537. {
  2538. int TileId;
  2539. int sx, sy;
  2540. int TileX, TileY;
  2541. /* see nothing if blind */
  2542. if (c[BLINDCOUNT]) return;
  2543. /* we end up knowing about it */
  2544. know[x][y] = item[x][y];
  2545. if (mitem[x][y].mon != MONST_NONE)
  2546. {
  2547. stealth[x][y] |= STEALTH_SEEN;
  2548. }
  2549. sx = x - MapTileLeft;
  2550. sy = y - MapTileTop;
  2551. if ((sx < 0) || (sx >= MapTileWidth) ||
  2552. (sy < 0) || (sy >= MapTileHeight))
  2553. {
  2554. //
  2555. // Tile is not currently in the visible part of the map,
  2556. // so don't draw anything
  2557. //
  2558. return;
  2559. }
  2560. GetTile(x, y, &TileId);
  2561. TileX = (TileId % 16) * TileWidth;
  2562. TileY = (TileId / 16) * TileHeight;
  2563. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  2564. TileX, TileY,
  2565. TileWidth, TileHeight,
  2566. MapLeft + sx*TileWidth, MapTop + sy*TileHeight);
  2567. }
  2568. /* =============================================================================
  2569. * FUNCTION: showplayer
  2570. */
  2571. void showplayer(void)
  2572. {
  2573. int sx, sy;
  2574. int TileId;
  2575. int TileX, TileY;
  2576. int scroll;
  2577. //
  2578. // Determine if we need to scroll the map
  2579. //
  2580. scroll = calc_scroll();
  2581. if (scroll)
  2582. {
  2583. PaintMap();
  2584. }
  2585. else
  2586. {
  2587. sx = playerx - MapTileLeft;
  2588. sy = playery - MapTileTop;
  2589. if ((sx >= 0) && (sx < MapTileWidth) &&
  2590. (sy >= 0) && (sy < MapTileHeight))
  2591. {
  2592. if (c[BLINDCOUNT] == 0)
  2593. {
  2594. TileId = PlayerTiles[class_num][(int) sex];
  2595. }
  2596. else
  2597. {
  2598. GetTile(playerx, playery, &TileId);
  2599. }
  2600. TileX = (TileId % 16) * TileWidth;
  2601. TileY = (TileId / 16) * TileHeight;
  2602. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  2603. TileX, TileY,
  2604. TileWidth, TileHeight,
  2605. MapLeft + sx*TileWidth, MapTop + sy*TileHeight);
  2606. TileId = TILE_CURSOR1;
  2607. TileX = (TileId % 16) * TileWidth;
  2608. TileY = (TileId / 16) * TileHeight;
  2609. XSetClipOrigin(display, ularn_gc,
  2610. MapLeft + sx*TileWidth - TileX,
  2611. MapTop + sy*TileHeight - TileY);
  2612. XSetClipMask(display, ularn_gc, TilePShape);
  2613. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  2614. TileX, TileY,
  2615. TileWidth, TileHeight,
  2616. MapLeft + sx*TileWidth,
  2617. MapTop + sy*TileHeight);
  2618. XSetClipOrigin(display, ularn_gc, 0, 0);
  2619. XSetClipMask(display, ularn_gc, None);
  2620. } /* If player on visible map area */
  2621. }
  2622. }
  2623. /* =============================================================================
  2624. * FUNCTION: showcell
  2625. */
  2626. void showcell(int x, int y)
  2627. {
  2628. int minx, maxx;
  2629. int miny, maxy;
  2630. int mx, my;
  2631. int sx, sy;
  2632. int TileX, TileY;
  2633. int TileId;
  2634. int scroll;
  2635. //
  2636. // Determine if we need to scroll the map
  2637. //
  2638. scroll = calc_scroll();
  2639. /*
  2640. * Decide how much the player knows about around him/her.
  2641. */
  2642. if (c[AWARENESS])
  2643. {
  2644. minx = x-3;
  2645. maxx = x+3;
  2646. miny = y-3;
  2647. maxy = y+3;
  2648. }
  2649. else
  2650. {
  2651. minx = x-1;
  2652. maxx = x+1;
  2653. miny = y-1;
  2654. maxy = y+1;
  2655. }
  2656. if (c[BLINDCOUNT])
  2657. {
  2658. minx = x;
  2659. maxx = x;
  2660. miny = y;
  2661. maxy = y;
  2662. //
  2663. // Redraw the last player position to remove the cursor
  2664. //
  2665. if (!scroll)
  2666. {
  2667. //
  2668. // Only redraw if the map is not going to be completely redrawn.
  2669. //
  2670. sx = lastpx - MapTileLeft;
  2671. sy = lastpy - MapTileTop;
  2672. if ((sx >= 0) && (sx < MapTileWidth) &&
  2673. (sy >= 0) && (sy < MapTileHeight))
  2674. {
  2675. //
  2676. // Tile is currently visible, so draw it
  2677. //
  2678. GetTile(lastpx, lastpy, &TileId);
  2679. TileX = (TileId % 16) * TileWidth;
  2680. TileY = (TileId / 16) * TileHeight;
  2681. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  2682. TileX, TileY,
  2683. TileWidth, TileHeight,
  2684. MapLeft + sx*TileWidth, MapTop + sy*TileHeight);
  2685. }
  2686. }
  2687. }
  2688. /*
  2689. * Limit the area to the map extents
  2690. */
  2691. if (minx < 0) minx = 0;
  2692. if (maxx > MAXX-1) maxx = MAXX-1;
  2693. if (miny < 0) miny=0;
  2694. if (maxy > MAXY-1) maxy = MAXY-1;
  2695. for (my = miny; my <= maxy; my++)
  2696. {
  2697. for (mx = minx; mx <= maxx; mx++)
  2698. {
  2699. if ((mx == playerx) && (my == playery))
  2700. {
  2701. know[mx][my] = item[mx][my];
  2702. if (!scroll)
  2703. {
  2704. //
  2705. // Only draw if the entire map is not going to be scrolled
  2706. //
  2707. showplayer();
  2708. }
  2709. }
  2710. else if ((know[mx][my] != item[mx][my]) || /* item changed */
  2711. ((mx == lastpx) && (my == lastpy)) || /* last player pos */
  2712. ((mitem[mx][my].mon != MONST_NONE) && /* unseen monster */
  2713. ((stealth[mx][my] & STEALTH_SEEN) == 0)))
  2714. {
  2715. //
  2716. // Only draw areas not already known (and hence displayed)
  2717. //
  2718. know[mx][my] = item[mx][my];
  2719. if (mitem[mx][my].mon != MONST_NONE)
  2720. {
  2721. stealth[mx][my] |= STEALTH_SEEN;
  2722. }
  2723. if (!scroll)
  2724. {
  2725. //
  2726. // Only draw the tile if the map is not going to be scrolled
  2727. //
  2728. sx = mx - MapTileLeft;
  2729. sy = my - MapTileTop;
  2730. if ((sx >= 0) && (sx < MapTileWidth) &&
  2731. (sy >= 0) && (sy < MapTileHeight))
  2732. {
  2733. //
  2734. // Tile is currently visible, so draw it
  2735. //
  2736. GetTile(mx, my, &TileId);
  2737. TileX = (TileId % 16) * TileWidth;
  2738. TileY = (TileId / 16) * TileHeight;
  2739. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  2740. TileX, TileY,
  2741. TileWidth, TileHeight,
  2742. MapLeft + sx*TileWidth, MapTop + sy*TileHeight);
  2743. }
  2744. }
  2745. } // if not known
  2746. }
  2747. }
  2748. if (scroll)
  2749. {
  2750. /* scrolling the map window, so repaint everything and return */
  2751. PaintMap();
  2752. }
  2753. }
  2754. /* =============================================================================
  2755. * FUNCTION: drawscreen
  2756. */
  2757. void drawscreen(void)
  2758. {
  2759. PaintWindow();
  2760. }
  2761. /* =============================================================================
  2762. * FUNCTION: draws
  2763. */
  2764. void draws(int minx, int miny, int maxx, int maxy)
  2765. {
  2766. PaintWindow();
  2767. }
  2768. /* =============================================================================
  2769. * FUNCTION: mapeffect
  2770. */
  2771. void mapeffect(int x, int y, DirEffectsType effect, int dir)
  2772. {
  2773. int TileId;
  2774. int sx, sy;
  2775. int TileX, TileY;
  2776. /* see nothing if blind */
  2777. if (c[BLINDCOUNT]) return;
  2778. sx = x - MapTileLeft;
  2779. sy = y - MapTileTop;
  2780. if ((sx < 0) || (sx >= MapTileWidth) ||
  2781. (sy < 0) || (sy >= MapTileHeight))
  2782. {
  2783. //
  2784. // Tile is not currently in the visible part of the map,
  2785. // so don't draw anything
  2786. //
  2787. return;
  2788. }
  2789. TileId = EffectTile[effect][dir];
  2790. TileX = (TileId % 16) * TileWidth;
  2791. TileY = (TileId / 16) * TileHeight;
  2792. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  2793. TileX, TileY,
  2794. TileWidth, TileHeight,
  2795. MapLeft + sx*TileWidth, MapTop + sy*TileHeight);
  2796. }
  2797. /* =============================================================================
  2798. * FUNCTION: magic_effect_frames
  2799. */
  2800. int magic_effect_frames(MagicEffectsType fx)
  2801. {
  2802. return magicfx_tile[fx].Frames;
  2803. }
  2804. /* =============================================================================
  2805. * FUNCTION: magic_effect
  2806. */
  2807. void magic_effect(int x, int y, MagicEffectsType fx, int frame)
  2808. {
  2809. int TileId;
  2810. int sx, sy;
  2811. int TileX, TileY;
  2812. if (frame > magicfx_tile[fx].Frames)
  2813. {
  2814. return;
  2815. }
  2816. /*
  2817. * draw the tile that is at this location
  2818. */
  2819. /* see nothing if blind */
  2820. if (c[BLINDCOUNT]) return;
  2821. sx = x - MapTileLeft;
  2822. sy = y - MapTileTop;
  2823. if ((sx < 0) || (sx >= MapTileWidth) ||
  2824. (sy < 0) || (sy >= MapTileHeight))
  2825. {
  2826. //
  2827. // Tile is not currently in the visible part of the map,
  2828. // so don't draw anything
  2829. //
  2830. return;
  2831. }
  2832. if (magicfx_tile[fx].Overlay)
  2833. {
  2834. GetTile(x, y, &TileId);
  2835. TileX = (TileId % 16) * TileWidth;
  2836. TileY = (TileId / 16) * TileHeight;
  2837. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  2838. TileX, TileY,
  2839. TileWidth, TileHeight,
  2840. MapLeft + sx*TileWidth, MapTop + sy*TileHeight);
  2841. TileId = magicfx_tile[fx].Tile1[frame];
  2842. TileX = (TileId % 16) * TileWidth;
  2843. TileY = (TileId / 16) * TileHeight;
  2844. XSetClipOrigin(display, ularn_gc,
  2845. MapLeft + sx*TileWidth - TileX,
  2846. MapTop + sy*TileHeight - TileY);
  2847. XSetClipMask(display, ularn_gc, TilePShape);
  2848. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  2849. TileX, TileY,
  2850. TileWidth, TileHeight,
  2851. MapLeft + sx*TileWidth,
  2852. MapTop + sy*TileHeight);
  2853. XSetClipOrigin(display, ularn_gc, 0, 0);
  2854. XSetClipMask(display, ularn_gc, None);
  2855. }
  2856. else
  2857. {
  2858. TileId = magicfx_tile[fx].Tile1[frame];
  2859. TileX = (TileId % 16) * TileWidth;
  2860. TileY = (TileId / 16) * TileHeight;
  2861. XCopyArea(display, TilePixmap, ularn_window, ularn_gc,
  2862. TileX, TileY,
  2863. TileWidth, TileHeight,
  2864. MapLeft + sx*TileWidth, MapTop + sy*TileHeight);
  2865. }
  2866. }
  2867. /* =============================================================================
  2868. * FUNCTION: nap
  2869. */
  2870. void nap(int delay)
  2871. {
  2872. XFlush(display);
  2873. XSync(display, 0);
  2874. usleep(delay * 1000);
  2875. }
  2876. /* =============================================================================
  2877. * FUNCTION: GetUser
  2878. */
  2879. void GetUser(char *username, int *uid)
  2880. {
  2881. *uid = getuid();
  2882. strcpy(username, getenv("USER"));
  2883. }